Merge "Remove test cases for the comparison with a binary asset" into gingerbread
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 0537d15..7c0cd5e 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -12,9 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-CTS_APPS_LIST := \
-    CtsVerifier
-
 CTS_SECURITY_APPS_LIST := \
 	CtsAppAccessData \
 	CtsAppWithData \
@@ -75,6 +72,5 @@
 	SignatureTest \
 	ApiDemos \
 	ApiDemosReferenceTest \
-	$(CTS_APPS_LIST) \
 	$(CTS_COVERAGE_TEST_CASE_LIST) \
 	$(CTS_SECURITY_APPS_LIST)
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 68c3682..14639d4 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -17,8 +17,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
-      android:versionCode="3"
-      android:versionName="2.3_r5">
+      android:versionCode="1"
+      android:versionName="2.3_r1">
       
     <uses-sdk android:minSdkVersion="5"></uses-sdk>
 
@@ -30,7 +30,13 @@
     <!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
-    <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true">
+    <application android:label="@string/app_name" 
+            android:icon="@drawable/icon"
+            android:backupAgent="VerifierBackupAgent" 
+            android:debuggable="true">
+            
+        <meta-data android:name="com.google.android.backup.api_key"
+                android:value="AEdPqrEAAAAIbK6ldcOzoeRtQ1u1dFVJ1A7KetRhit-a1Xa82Q" />
 
         <activity android:name=".CtsVerifierActivity" android:label="@string/app_name">
             <intent-filter>
@@ -73,6 +79,13 @@
             </intent-filter>
         </receiver>
 
+        <activity android:name=".backup.BackupTestActivity" android:label="@string/backup_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".bluetooth.BluetoothTestActivity"
                 android:label="@string/bluetooth_test"
                 android:configChanges="keyboardHidden|orientation">
diff --git a/apps/CtsVerifier/res/layout/bu_main.xml b/apps/CtsVerifier/res/layout/bu_main.xml
new file mode 100644
index 0000000..2289fee
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/bu_main.xml
@@ -0,0 +1,44 @@
+<?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:orientation="vertical"
+         android:layout_width="match_parent"
+         android:layout_height="match_parent"
+         >
+         
+    <ListView android:id="@+id/android:list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            />
+            
+    <TextView android:id="@id/android:empty"
+           android:gravity="center"
+           android:layout_width="match_parent"
+           android:layout_height="wrap_content"
+           android:layout_weight="1"
+           android:text="@string/bu_loading"
+           />
+
+    <Button android:id="@+id/generate_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/bu_generate"
+            />
+
+    <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/bu_preference_row.xml b/apps/CtsVerifier/res/layout/bu_preference_row.xml
new file mode 100644
index 0000000..c37eece
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/bu_preference_row.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="18sp"
+        android:padding="5dp"
+        />
diff --git a/apps/CtsVerifier/res/menu/test_list_menu.xml b/apps/CtsVerifier/res/menu/test_list_menu.xml
index 495e36f..16323e9 100644
--- a/apps/CtsVerifier/res/menu/test_list_menu.xml
+++ b/apps/CtsVerifier/res/menu/test_list_menu.xml
@@ -7,6 +7,6 @@
           android:icon="@android:drawable/ic_menu_upload"
           android:title="@string/copy" />
     <item android:id="@+id/export"
-          android:icon="@android:drawable/ic_menu_share"
+          android:icon="@android:drawable/ic_menu_save"
           android:title="@string/export" />
 </menu>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0f0f645..628b931 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -44,6 +44,32 @@
     <string name="no_storage">Cannot save report to external storage, see log for details.</string>
     <string name="report_saved">Report saved to: %s</string>
 
+    <!-- Strings for BackupTestActivity -->
+    <string name="backup_test">Data Backup Test</string>
+    <string name="backup_info">This test checks that data backup and automatic restore works 
+        properly. The test activity lists some preferences and files that are backed up and
+        restored by the CTS Verifier. If backup and restore is working properly, these values
+        should be restored after running the backup manager, uninstalling the app, and reinstalling
+        the CTS Verifier.
+        \n\nPress the \"Generate Test Data\" to populate these values
+        and then follow the on screen instructions to finish the test.
+    </string>
+    <string name="bu_preferences">Preferences</string>
+    <string name="bu_files">Files</string>
+    <string name="bu_loading">Loading...</string>
+    <string name="bu_generate">Generate Test Data</string>
+    <string name="bu_generate_error">Error occurred while generating test data...</string>
+    <string name="bu_instructions">Random values for the preferences and files have been saved.
+        \n\nFollow the instructions below to check that the data backup and restore works:
+        \n\n1. Make sure backup and automatic restore are enabled in settings. Depending on the 
+        backup transport supported by the device you may need to do additional steps. For instance 
+        you may need to set a Google account as the backup account for the device.
+        \n\n2. Run the backup manager: adb shell bmgr run
+        \n\n3. Uninstall the program: adb uninstall com.android.cts.verifier
+        \n\n4. Reinstall the CTS Verifier and verify that the values are still the same.
+    </string>
+    <string name="bu_settings">Settings</string>
+
     <!-- Strings for Device Administration tests -->
     <string name="da_policy_serialization_test">Policy Serialization Test</string>
     <string name="da_policy_serialization_info">This test checks that a device policy is properly
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index f6e6f1b..38b4dbc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -350,18 +350,7 @@
 
         @Override
         protected Void doInBackground(Void... params) {
-            ContentValues values = new ContentValues(2);
-            values.put(TestResultsProvider.COLUMN_TEST_RESULT, mResult);
-            values.put(TestResultsProvider.COLUMN_TEST_NAME, mTestName);
-
-            ContentResolver resolver = mContext.getContentResolver();
-            int numUpdated = resolver.update(TestResultsProvider.RESULTS_CONTENT_URI, values,
-                    TestResultsProvider.COLUMN_TEST_NAME + " = ?",
-                    new String[] {mTestName});
-
-            if (numUpdated == 0) {
-                resolver.insert(TestResultsProvider.RESULTS_CONTENT_URI, values);
-            }
+            TestResultsProvider.setTestResult(mContext, mTestName, mResult);
             return null;
         }
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
new file mode 100644
index 0000000..0966de4
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
@@ -0,0 +1,131 @@
+/*
+ * 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.verifier;
+
+import com.android.cts.verifier.backup.BackupTestActivity;
+
+import android.app.backup.BackupDataInputStream;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupHelper;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/** {@link BackupHelper} for the test results database. */
+class TestResultsBackupHelper implements BackupHelper {
+
+    private static final String TAG = TestResultsBackupHelper.class.getSimpleName();
+
+    private static final String DB_BACKUP_KEY = "db";
+
+    private final Context mContext;
+
+    TestResultsBackupHelper(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState) {
+        ContentResolver resolver = mContext.getContentResolver();
+        Cursor cursor = null;
+        try {
+            cursor = resolver.query(TestResultsProvider.RESULTS_CONTENT_URI,
+                    null, null, null, null);
+            int nameIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_NAME);
+            int resultIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_RESULT);
+            int infoSeenIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_INFO_SEEN);
+
+            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
+            DataOutputStream dataOutput = new DataOutputStream(byteOutput);
+
+            dataOutput.writeInt(cursor.getCount());
+            while (cursor.moveToNext()) {
+                String name = cursor.getString(nameIndex);
+                int result = cursor.getInt(resultIndex);
+                int infoSeen = cursor.getInt(infoSeenIndex);
+
+                dataOutput.writeUTF(name);
+                dataOutput.writeInt(result);
+                dataOutput.writeInt(infoSeen);
+            }
+
+            byte[] rawBytes = byteOutput.toByteArray();
+            data.writeEntityHeader(DB_BACKUP_KEY, rawBytes.length);
+            data.writeEntityData(rawBytes, rawBytes.length);
+        } catch (IOException e) {
+            Log.e(TAG, "Couldn't backup test results...", e);
+            failBackupTest();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    @Override
+    public void restoreEntity(BackupDataInputStream data) {
+        try {
+            if (DB_BACKUP_KEY.equals(data.getKey())) {
+                byte[] rawBytes = new byte[data.size()];
+                data.read(rawBytes, 0, data.size());
+
+                ByteArrayInputStream byteInput = new ByteArrayInputStream(rawBytes);
+                DataInputStream dataInput = new DataInputStream(byteInput);
+
+                int numRows = dataInput.readInt();
+                ContentValues[] values = new ContentValues[numRows];
+                for (int i = 0; i < numRows; i++) {
+                    String name = dataInput.readUTF();
+                    int result = dataInput.readInt();
+                    int infoSeen = dataInput.readInt();
+
+                    values[i] = new ContentValues();
+                    values[i].put(TestResultsProvider.COLUMN_TEST_NAME, name);
+                    values[i].put(TestResultsProvider.COLUMN_TEST_RESULT, result);
+                    values[i].put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, infoSeen);
+                }
+
+                ContentResolver resolver = mContext.getContentResolver();
+                resolver.bulkInsert(TestResultsProvider.RESULTS_CONTENT_URI, values);
+            } else {
+                failBackupTest();
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Couldn't restore test results...", e);
+            failBackupTest();
+        }
+    }
+
+    private void failBackupTest() {
+        TestResultsProvider.setTestResult(mContext, BackupTestActivity.class.getName(),
+                TestResult.TEST_RESULT_FAILED);
+    }
+
+    @Override
+    public void writeNewStateDescription(ParcelFileDescriptor newState) {
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
index a41cb43..cc9dc73 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsProvider.java
@@ -16,7 +16,9 @@
 
 package com.android.cts.verifier;
 
+import android.app.backup.BackupManager;
 import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.UriMatcher;
@@ -40,18 +42,18 @@
         return Uri.withAppendedPath(RESULTS_CONTENT_URI, testName);
     }
 
-    public static final String _ID = "_id";
+    static final String _ID = "_id";
 
     /** String name of the test like "com.android.cts.verifier.foo.FooTestActivity" */
-    public static final String COLUMN_TEST_NAME = "testname";
+    static final String COLUMN_TEST_NAME = "testname";
 
     /** Integer test result corresponding to constants in {@link TestResult}. */
-    public static final String COLUMN_TEST_RESULT = "testresult";
+    static final String COLUMN_TEST_RESULT = "testresult";
 
     /** Boolean indicating whether the test info has been seen. */
-    public static final String COLUMN_TEST_INFO_SEEN = "testinfoseen";
+    static final String COLUMN_TEST_INFO_SEEN = "testinfoseen";
 
-    public static final String[] ALL_COLUMNS = {
+    static final String[] ALL_COLUMNS = {
         _ID,
         COLUMN_TEST_NAME,
         COLUMN_TEST_RESULT,
@@ -72,9 +74,12 @@
 
     private SQLiteOpenHelper mOpenHelper;
 
+    private BackupManager mBackupManager;
+
     @Override
     public boolean onCreate() {
         mOpenHelper = new TestResultsOpenHelper(getContext());
+        mBackupManager = new BackupManager(getContext());
         return false;
     }
 
@@ -140,14 +145,12 @@
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         long id = db.insert(TABLE_NAME, null, values);
         getContext().getContentResolver().notifyChange(uri, null);
+        mBackupManager.dataChanged();
         return Uri.withAppendedPath(RESULTS_CONTENT_URI, "" + id);
-
     }
 
     @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-
         int match = URI_MATCHER.match(uri);
         switch (match) {
             case RESULTS_ALL:
@@ -176,9 +179,11 @@
                 throw new IllegalArgumentException("Unknown URI: " + uri);
         }
 
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         int numUpdated = db.update(TABLE_NAME, values, selection, selectionArgs);
         if (numUpdated > 0) {
             getContext().getContentResolver().notifyChange(uri, null);
+            mBackupManager.dataChanged();
         }
         return numUpdated;
     }
@@ -189,6 +194,7 @@
         int numDeleted = db.delete(TABLE_NAME, selection, selectionArgs);
         if (numDeleted > 0) {
             getContext().getContentResolver().notifyChange(uri, null);
+            mBackupManager.dataChanged();
         }
         return numDeleted;
     }
@@ -197,4 +203,20 @@
     public String getType(Uri uri) {
         return null;
     }
+
+    static void setTestResult(Context context, String testName, int testResult) {
+        ContentValues values = new ContentValues(2);
+        values.put(TestResultsProvider.COLUMN_TEST_RESULT, testResult);
+        values.put(TestResultsProvider.COLUMN_TEST_NAME, testName);
+
+        ContentResolver resolver = context.getContentResolver();
+        int numUpdated = resolver.update(TestResultsProvider.RESULTS_CONTENT_URI, values,
+                TestResultsProvider.COLUMN_TEST_NAME + " = ?",
+                new String[] {testName});
+
+        if (numUpdated == 0) {
+            resolver.insert(TestResultsProvider.RESULTS_CONTENT_URI, values);
+        }
+    }
+
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java b/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
new file mode 100644
index 0000000..3c980b9
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
@@ -0,0 +1,32 @@
+/*
+ * 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.verifier;
+
+import com.android.cts.verifier.backup.BackupTestActivity;
+
+import android.app.backup.BackupAgentHelper;
+
+public class VerifierBackupAgent extends BackupAgentHelper {
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        addHelper("test-results", new TestResultsBackupHelper(this));
+        addHelper("backup-test-prefs", BackupTestActivity.getSharedPreferencesBackupHelper(this));
+        addHelper("backup-test-files", BackupTestActivity.getFileBackupHelper(this));
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
new file mode 100644
index 0000000..cccc1c2
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
@@ -0,0 +1,404 @@
+/*
+ * 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.verifier.backup;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.backup.BackupManager;
+import android.app.backup.FileBackupHelper;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Scanner;
+
+/**
+ * Test for checking whether the BackupManager is working properly. It lists the values of
+ * several preferences and contents of files that should get backed up and restored after
+ * running the backup manager and reinstalling the CTS verifier.
+ */
+public class BackupTestActivity extends PassFailButtons.ListActivity {
+
+    private static final String TAG = BackupTestActivity.class.getSimpleName();
+
+    private static final int INSTRUCTIONS_DIALOG_ID = 1;
+
+    private static final String TEST_PREFS_1 = "test-prefs-1";
+    private static final String INT_PREF = "int-pref";
+    private static final String BOOL_PREF = "bool-pref";
+
+    private static final String TEST_PREFS_2 = "test-prefs-2";
+    private static final String FLOAT_PREF = "float-pref";
+    private static final String LONG_PREF = "long-pref";
+    private static final String STRING_PREF = "string-pref";
+
+    private static final String TEST_FILE_1 = "test-file-1";
+    private static final String TEST_FILE_2 = "test-file-2";
+
+    private BackupAdapter mAdapter;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+        setContentView(R.layout.bu_main);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.backup_test, R.string.backup_info, 0);
+
+        mAdapter = new BackupAdapter(this);
+        setListAdapter(mAdapter);
+
+        new LoadBackupItemsTask().execute();
+
+        findViewById(R.id.generate_button).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                new GenerateValuesTask().execute();
+            }
+        });
+    }
+
+    public static SharedPreferencesBackupHelper getSharedPreferencesBackupHelper(Context context) {
+        return new SharedPreferencesBackupHelper(context, TEST_PREFS_1, TEST_PREFS_2);
+    }
+
+    public static FileBackupHelper getFileBackupHelper(Context context) {
+        return new FileBackupHelper(context, TEST_FILE_1, TEST_FILE_2);
+    }
+
+    class LoadBackupItemsTask extends AsyncTask<Void, Void, List<BackupItem>> {
+
+        @Override
+        protected void onPreExecute() {
+            super.onPreExecute();
+            setProgressBarIndeterminateVisibility(true);
+        }
+
+        @Override
+        protected List<BackupItem> doInBackground(Void... params) {
+            List<BackupItem> items = new ArrayList<BackupItem>();
+
+            items.add(new CategoryBackupItem(R.string.bu_preferences));
+            loadPreferenceGroup1(items);
+            loadPreferenceGroup2(items);
+
+            items.add(new CategoryBackupItem(R.string.bu_files));
+            loadFile(TEST_FILE_1, items);
+            loadFile(TEST_FILE_2, items);
+
+            return items;
+        }
+
+        private void loadPreferenceGroup1(List<BackupItem> items) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+
+            int intValue = prefs.getInt(INT_PREF, 0);
+            items.add(new PreferenceBackupItem(TEST_PREFS_1, INT_PREF, "" + intValue));
+
+            boolean boolValue = prefs.getBoolean(BOOL_PREF, false);
+            items.add(new PreferenceBackupItem(TEST_PREFS_1, BOOL_PREF, "" + boolValue));
+        }
+
+        private void loadPreferenceGroup2(List<BackupItem> items) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+
+            float floatValue = prefs.getFloat(FLOAT_PREF, 0.0f);
+            items.add(new PreferenceBackupItem(TEST_PREFS_2, FLOAT_PREF, "" + floatValue));
+
+            long longValue = prefs.getLong(LONG_PREF, 0L);
+            items.add(new PreferenceBackupItem(TEST_PREFS_2, LONG_PREF, "" + longValue));
+
+            String stringValue = prefs.getString(STRING_PREF, null);
+            items.add(new PreferenceBackupItem(TEST_PREFS_2, STRING_PREF, stringValue));
+        }
+
+        private void loadFile(String fileName, List<BackupItem> items) {
+            StringBuilder contents = new StringBuilder();
+            Scanner scanner = null;
+            try {
+                scanner = new Scanner(new File(getFilesDir(), fileName));
+                while (scanner.hasNext()) {
+                    contents.append(scanner.nextLine());
+                }
+                scanner.close();
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Couldn't find test file but this may be fine...", e);
+            } finally {
+                if (scanner != null) {
+                    scanner.close();
+                }
+            }
+            items.add(new FileBackupItem(fileName, contents.toString()));
+        }
+
+        @Override
+        protected void onPostExecute(List<BackupItem> result) {
+            super.onPostExecute(result);
+            setProgressBarIndeterminateVisibility(false);
+            mAdapter.clear();
+            mAdapter.addAll(result);
+        }
+    }
+
+    class GenerateValuesTask extends AsyncTask<Void, Void, Exception> {
+
+        @Override
+        protected Exception doInBackground(Void... params) {
+            Random random = new Random();
+            generatePreferenceGroup1(random);
+            generatePreferenceGroup2(random);
+            try {
+                generateTestFile(TEST_FILE_1, random);
+                generateTestFile(TEST_FILE_2, random);
+            } catch (FileNotFoundException e) {
+                return e;
+            }
+            return null;
+        }
+
+        private void generatePreferenceGroup1(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putInt(INT_PREF, (random.nextInt(100) + 1));
+            editor.putBoolean(BOOL_PREF, random.nextBoolean());
+            editor.commit();
+        }
+
+        private void generatePreferenceGroup2(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putFloat(FLOAT_PREF, random.nextFloat());
+            editor.putLong(LONG_PREF, random.nextLong());
+            editor.putString(STRING_PREF, "Random number: " + (random.nextInt(100) + 1));
+            editor.commit();
+        }
+
+        private void generateTestFile(String fileName, Random random)
+                throws FileNotFoundException {
+            File file = new File(getFilesDir(), fileName);
+            PrintWriter writer = new PrintWriter(file);
+            writer.write("Random number: " + (random.nextInt(100) + 1));
+            writer.close();
+        }
+
+        @Override
+        protected void onPostExecute(Exception exception) {
+            super.onPostExecute(exception);
+            if (exception != null) {
+                Log.e(TAG, "Couldn't generate test data...", exception);
+                Toast.makeText(BackupTestActivity.this, R.string.bu_generate_error,
+                        Toast.LENGTH_LONG).show();
+            } else {
+                showDialog(INSTRUCTIONS_DIALOG_ID);
+
+                BackupManager backupManager = new BackupManager(BackupTestActivity.this);
+                backupManager.dataChanged();
+
+                new LoadBackupItemsTask().execute();
+            }
+        }
+    }
+
+    @Override
+    public Dialog onCreateDialog(int id, Bundle args) {
+        switch (id) {
+            case INSTRUCTIONS_DIALOG_ID:
+                return new AlertDialog.Builder(this)
+                    .setIcon(android.R.drawable.ic_dialog_info)
+                    .setTitle(R.string.backup_test)
+                    .setMessage(R.string.bu_instructions)
+                    .setPositiveButton(android.R.string.ok, null)
+                    .setNeutralButton(R.string.bu_settings, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
+                        }
+                    })
+                    .create();
+
+            default:
+                return super.onCreateDialog(id, args);
+        }
+    }
+
+    interface BackupItem {
+        int getViewType();
+        View getView(LayoutInflater inflater, int position, View convertView, ViewGroup parent);
+    }
+
+    static class CategoryBackupItem implements BackupItem {
+
+        private final int mTitleResId;
+
+        CategoryBackupItem(int titleResId) {
+            mTitleResId = titleResId;
+        }
+
+        @Override
+        public int getViewType() {
+            return 0;
+        }
+
+        @Override
+        public View getView(LayoutInflater inflater, int position, View convertView,
+                ViewGroup parent) {
+            TextView view = (TextView) convertView;
+            if (convertView == null) {
+                view = (TextView) inflater.inflate(R.layout.test_category_row, parent, false);
+            }
+            view.setText(mTitleResId);
+            return view;
+        }
+    }
+
+    static class PreferenceBackupItem implements BackupItem {
+
+        private final String mGroup;
+
+        private final String mName;
+
+        private final String mValue;
+
+        PreferenceBackupItem(String group, String name, String value) {
+            mGroup = group;
+            mName = name;
+            mValue = value;
+        }
+
+        @Override
+        public int getViewType() {
+            return 1;
+        }
+
+        @Override
+        public View getView(LayoutInflater inflater, int position, View convertView,
+                ViewGroup parent) {
+            TextView view = (TextView) convertView;
+            if (convertView == null) {
+                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
+            }
+            view.setText(mGroup + "/" + mName + " : " + mValue);
+            return view;
+        }
+    }
+
+    static class FileBackupItem implements BackupItem {
+
+        private final String mName;
+
+        private final String mContents;
+
+        FileBackupItem(String name, String contents) {
+            mName = name;
+            mContents = contents;
+        }
+
+        @Override
+        public int getViewType() {
+            return 2;
+        }
+
+        @Override
+        public View getView(LayoutInflater inflater, int position, View convertView,
+                ViewGroup parent) {
+            TextView view = (TextView) convertView;
+            if (convertView == null) {
+                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
+            }
+            view.setText(mName + " : " + mContents);
+            return view;
+        }
+    }
+
+    class BackupAdapter extends BaseAdapter {
+
+        private final LayoutInflater mLayoutInflater;
+
+        private final List<BackupItem> mItems = new ArrayList<BackupItem>();
+
+        public BackupAdapter(Context context) {
+            mLayoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
+        }
+
+        public void clear() {
+            mItems.clear();
+        }
+
+        public void addAll(List<BackupItem> items) {
+            mItems.addAll(items);
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mItems.size();
+        }
+
+        @Override
+        public BackupItem getItem(int position) {
+            return mItems.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public boolean isEnabled(int position) {
+            return false;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return 3;
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return getItem(position).getViewType();
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            return getItem(position).getView(mLayoutInflater, position, convertView, parent);
+        }
+    }
+}
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz.3gp
new file mode 100644
index 0000000..f274033
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz.3gp
new file mode 100644
index 0000000..1352250
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz.3gp
new file mode 100644
index 0000000..d410946
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp
new file mode 100644
index 0000000..b62a388
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz.3gp
new file mode 100644
index 0000000..c51d6ed
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_22050hz.3gp
new file mode 100644
index 0000000..321d761
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz.3gp
new file mode 100644
index 0000000..ac17582
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz.3gp
new file mode 100644
index 0000000..c212fab
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz.3gp
new file mode 100644
index 0000000..085f487
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz.3gp
new file mode 100644
index 0000000..4931cc9
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_22050hz.3gp
new file mode 100644
index 0000000..9d89e57
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz.3gp
new file mode 100644
index 0000000..56dcf59
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz.3gp
new file mode 100644
index 0000000..8565f63
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz.3gp
new file mode 100644
index 0000000..7485c4f
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_22050hz.3gp
new file mode 100644
index 0000000..48e9509
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz.3gp
new file mode 100644
index 0000000..1d3ec3b
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_22050hz.3gp
new file mode 100644
index 0000000..4df6ff6
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz.3gp
new file mode 100644
index 0000000..68e17e9
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz.3gp
new file mode 100644
index 0000000..aec9de3
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz.3gp
new file mode 100644
index 0000000..b6862de
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_22050hz.3gp
new file mode 100644
index 0000000..600dbc0
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz.3gp
new file mode 100644
index 0000000..f341f3d
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_22050hz.3gp b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_22050hz.3gp
new file mode 100644
index 0000000..9fa8e48
--- /dev/null
+++ b/tests/res/raw/video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_22050hz.3gp
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..6388db4
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..3d9f388
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..ec70546
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..0ee179f
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz.mp4
new file mode 100644
index 0000000..f0f9c84
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..c3c9abc
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/res/raw/video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/res/raw/video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..09a1269
--- /dev/null
+++ b/tests/res/raw/video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java b/tests/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java
new file mode 100644
index 0000000..67e09a7
--- /dev/null
+++ b/tests/tests/app/src/android/app/backup/cts/BackupAgentHelperTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.app.backup.cts;
+
+import android.app.backup.BackupAgentHelper;
+import android.app.backup.FileBackupHelper;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.test.AndroidTestCase;
+
+public class BackupAgentHelperTest extends AndroidTestCase {
+
+    public void testBackupAgentHelper() {
+        BackupAgentHelper helper = new BackupAgentHelper();
+        helper.addHelper("prefs", new SharedPreferencesBackupHelper(mContext));
+        helper.addHelper("files", new FileBackupHelper(mContext));
+    }
+}
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupAgentTest.java b/tests/tests/app/src/android/app/backup/cts/BackupAgentTest.java
new file mode 100644
index 0000000..d3c3fd7
--- /dev/null
+++ b/tests/tests/app/src/android/app/backup/cts/BackupAgentTest.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.app.backup.cts;
+
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.os.ParcelFileDescriptor;
+import android.test.AndroidTestCase;
+
+import java.io.IOException;
+
+public class BackupAgentTest extends AndroidTestCase {
+
+    public void testBackupAgent() {
+        BackupAgent agent = new TestBackupAgent();
+        agent.onCreate();
+        agent.onDestroy();
+    }
+
+    class TestBackupAgent extends BackupAgent {
+
+        @Override
+        public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+                ParcelFileDescriptor newState) throws IOException {
+        }
+
+        @Override
+        public void onRestore(BackupDataInput data, int appVersionCode,
+                ParcelFileDescriptor newState) throws IOException {
+        }
+    }
+}
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java b/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
new file mode 100644
index 0000000..f21f847
--- /dev/null
+++ b/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.app.backup.cts;
+
+import android.app.backup.BackupManager;
+import android.app.backup.RestoreObserver;
+import android.test.AndroidTestCase;
+
+public class BackupManagerTest extends AndroidTestCase {
+
+    public void testBackupManager() throws Exception {
+        // Check that these don't crash as if they were called in an app...
+        BackupManager backupManager = new BackupManager(mContext);
+        backupManager.dataChanged();
+        BackupManager.dataChanged("com.android.cts.stub");
+
+        // Backup isn't expected to work in this test but check for obvious bugs...
+        int result = backupManager.requestRestore(new RestoreObserver() {});
+        assertTrue(result != 0);
+    }
+}
diff --git a/tests/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java b/tests/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java
new file mode 100644
index 0000000..bb09b7e
--- /dev/null
+++ b/tests/tests/app/src/android/app/backup/cts/FileBackupHelperTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.app.backup.cts;
+
+import android.app.backup.FileBackupHelper;
+import android.test.AndroidTestCase;
+
+public class FileBackupHelperTest extends AndroidTestCase {
+
+    public void testConstructor() {
+        new FileBackupHelper(mContext);
+        new FileBackupHelper(mContext, "test-file-1");
+        new FileBackupHelper(mContext, "test-file-1", "test-file-2");
+    }
+}
diff --git a/tests/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java b/tests/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java
new file mode 100644
index 0000000..a1f2488
--- /dev/null
+++ b/tests/tests/app/src/android/app/backup/cts/SharedPreferencesBackupHelperTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.app.backup.cts;
+
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.test.AndroidTestCase;
+
+public class SharedPreferencesBackupHelperTest extends AndroidTestCase {
+
+    public void testConstructor() {
+        new SharedPreferencesBackupHelper(mContext);
+        new SharedPreferencesBackupHelper(mContext, "test-prefs-group-1");
+        new SharedPreferencesBackupHelper(mContext, "test-prefs-group-1", "test-prefs-group-2");
+    }
+}
diff --git a/tests/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/tests/app/src/android/app/cts/DownloadManagerTest.java
index 3920d58..47ad42c 100644
--- a/tests/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -24,11 +24,13 @@
 import android.content.IntentFilter;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
 import android.view.animation.cts.DelayedCheck;
 import android.webkit.cts.CtsTestServer;
 
+import java.io.File;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -120,6 +122,66 @@
         }
     }
 
+    /**
+     * Set download locations and verify that file is downloaded to correct location.
+     *
+     * Checks three different methods of setting location: directly via setDestinationUri, and
+     * indirectly through setDestinationInExternalFilesDir and setDestinationinExternalPublicDir.
+     */
+    public void testDownloadManagerDestination() throws Exception {
+        File uriLocation = new File(mContext.getExternalFilesDir(null), "uriFile");
+        if (uriLocation.exists()) {
+            assertTrue(uriLocation.delete());
+        }
+
+        File extFileLocation = new File(mContext.getExternalFilesDir(null), "extFile");
+        if (extFileLocation.exists()) {
+            assertTrue(extFileLocation.delete());
+        }
+
+        File publicLocation = new File(
+                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
+                "publicFile");
+        if (publicLocation.exists()) {
+            assertTrue(publicLocation.delete());
+        }
+
+        DownloadCompleteReceiver receiver =
+            new DownloadCompleteReceiver(3, TimeUnit.SECONDS.toMillis(5));
+        try {
+            IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+            mContext.registerReceiver(receiver, intentFilter);
+
+            Request requestUri = new Request(getGoodUrl());
+            requestUri.setDestinationUri(Uri.fromFile(uriLocation));
+            long uriId = mDownloadManager.enqueue(requestUri);
+
+            Request requestExtFile = new Request(getGoodUrl());
+            requestExtFile.setDestinationInExternalFilesDir(mContext, null, "extFile");
+            long extFileId = mDownloadManager.enqueue(requestExtFile);
+
+            Request requestPublic = new Request(getGoodUrl());
+            requestPublic.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,
+                    "publicFile");
+            long publicId = mDownloadManager.enqueue(requestPublic);
+
+            int allDownloads = getTotalNumberDownloads();
+            assertEquals(3, allDownloads);
+
+            receiver.waitForDownloadComplete();
+
+            assertSuccessfulDownload(uriId, uriLocation);
+            assertSuccessfulDownload(extFileId, extFileLocation);
+            assertSuccessfulDownload(publicId, publicLocation);
+
+            assertRemoveDownload(uriId, allDownloads - 1);
+            assertRemoveDownload(extFileId, allDownloads - 2);
+            assertRemoveDownload(publicId, allDownloads - 3);
+        } finally {
+            mContext.unregisterReceiver(receiver);
+        }
+    }
+
     private class DownloadCompleteReceiver extends BroadcastReceiver {
 
         private final CountDownLatch mReceiveLatch;
@@ -220,6 +282,23 @@
         }.run();
     }
 
+    private void assertSuccessfulDownload(long id, File location) {
+        Cursor cursor = null;
+        try {
+            cursor = mDownloadManager.query(new Query().setFilterById(id));
+            assertTrue(cursor.moveToNext());
+            assertEquals(DownloadManager.STATUS_SUCCESSFUL, cursor.getInt(
+                    cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)));
+            assertEquals(Uri.fromFile(location).toString(),
+                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
+            assertTrue(location.exists());
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
     private void assertRemoveDownload(long removeId, int expectedNumDownloads) {
         Cursor cursor = null;
         try {
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 57c5c31..c519224 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -202,48 +202,7 @@
     }
 
     public void testSettings() {
-        assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_ADD_ACCOUNT));
-        assertCanBeHandled(new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_APN_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-                .setData(Uri.parse("package:com.android.cts.stub")));
-
-        // TODO: Uncomment in HC. This appears to be broken in Froyo and Gingerbread...
-        // assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
-
-        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_DATE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_LOCALE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
-
-        // TODO: Seems to not work at on NS, Xoom, Xoom WiFi
-        // assertCanBeHandled(new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS));
-
-        assertCanBeHandled(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
-
-        // TODO: Seems to not work at on NS, Xoom, Xoom WiFi
-        // assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
-
-        assertCanBeHandled(new Intent(Settings.ACTION_SEARCH_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_SECURITY_SETTINGS));
         assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_SOUND_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_SYNC_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_USER_DICTIONARY_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_IP_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
-        assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
     }
 
     /**
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index b4053cf..465b87a 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -553,11 +553,17 @@
                 // adjusting the volume to zero should result in either silent or vibrate mode
                 assertTrue(mAudioManager.getRingerMode() == RINGER_MODE_VIBRATE ||
                         mAudioManager.getRingerMode() == RINGER_MODE_SILENT);
+                int lastRingerMode = mAudioManager.getRingerMode();
                 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, FLAG_ALLOW_RINGER_MODES);
                 // There are two possible ways the device may work. It may have a silent/vibrate
                 // mode or it may have distinct silent and vibrate modes.
-                assertTrue(mAudioManager.getRingerMode() == RINGER_MODE_NORMAL ||
+                if (lastRingerMode == RINGER_MODE_VIBRATE) {
+                    assertTrue(mAudioManager.getRingerMode() == RINGER_MODE_NORMAL ||
+                        mAudioManager.getRingerMode() == RINGER_MODE_SILENT);
+                } else if (lastRingerMode == RINGER_MODE_SILENT) {
+                    assertTrue(mAudioManager.getRingerMode() == RINGER_MODE_NORMAL ||
                         mAudioManager.getRingerMode() == RINGER_MODE_VIBRATE);
+                }
                 // Increase the volume one more time to get out of the vibrate mode which may
                 // be separate from silent mode.
                 mAudioManager.adjustStreamVolume(streams[i], ADJUST_RAISE, FLAG_ALLOW_RINGER_MODES);
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
new file mode 100644
index 0000000..7d2bc81
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerStreamingTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.media.cts;
+
+import android.media.MediaPlayer;
+import android.webkit.cts.CtsTestServer;
+
+
+/**
+ * Tests of MediaPlayer streaming capabilities.
+ */
+public class MediaPlayerStreamingTest extends MediaPlayerTestBase {
+    private CtsTestServer mServer;
+
+    // Streaming audio from local HTTP server
+    public void testPlayMp3Stream1() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3Stream2() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", false, false);
+    }
+    public void testPlayMp3StreamRedirect() throws Throwable {
+        localHttpAudioStreamTest("ringer.mp3", true, false);
+    }
+    public void testPlayMp3StreamNoLength() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.mp3", false, true);
+    }
+    public void testPlayOggStream() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, false);
+    }
+    public void testPlayOggStreamRedirect() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", true, false);
+    }
+    public void testPlayOggStreamNoLength() throws Throwable {
+        localHttpAudioStreamTest("noiseandchirps.ogg", false, true);
+    }
+
+    private void localHttpAudioStreamTest(final String name, boolean redirect, boolean nolength)
+            throws Throwable {
+        mServer = new CtsTestServer(mContext);
+        try {
+            String stream_url = null;
+            if (redirect) {
+                // Stagefright doesn't have a limit, but we can't test support of infinite redirects
+                // Up to 4 redirects seems reasonable though.
+                stream_url = mServer.getRedirectingAssetUrl(name, 4);
+            } else {
+                stream_url = mServer.getAssetUrl(name);
+            }
+            if (nolength) {
+                stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
+            }
+
+            mMediaPlayer.setDataSource(stream_url);
+
+            mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+            mMediaPlayer.setScreenOnWhilePlaying(true);
+
+            mOnBufferingUpdateCalled.reset();
+            mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
+                @Override
+                public void onBufferingUpdate(MediaPlayer mp, int percent) {
+                    mOnBufferingUpdateCalled.signal();
+                }
+            });
+            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer mp, int what, int extra) {
+                    fail("Media player had error " + what + " playing " + name);
+                    return true;
+                }
+            });
+
+            assertFalse(mOnBufferingUpdateCalled.isSignalled());
+            mMediaPlayer.prepare();
+
+            if (nolength) {
+                mMediaPlayer.start();
+                Thread.sleep(LONG_SLEEP_TIME);
+                assertFalse(mMediaPlayer.isPlaying());
+            } else {
+                mOnBufferingUpdateCalled.waitForSignal();
+                mMediaPlayer.start();
+                Thread.sleep(SLEEP_TIME);
+            }
+            mMediaPlayer.stop();
+            mMediaPlayer.reset();
+        } finally {
+            mServer.shutdown();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index d18d684..dd5edd7 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -17,205 +17,33 @@
 
 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.Context;
 import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
-import android.media.MediaPlayer.OnBufferingUpdateListener;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
-import android.media.MediaPlayer.OnSeekCompleteListener;
-import android.media.MediaPlayer.OnVideoSizeChangedListener;
 import android.net.Uri;
 import android.os.Environment;
-import android.os.Looper;
 import android.os.PowerManager;
-import android.test.ActivityInstrumentationTestCase2;
-import android.view.SurfaceHolder;
-import android.webkit.cts.CtsTestServer;
-import android.util.Log;
 
 import java.io.File;
-import java.io.FileDescriptor;
 
-@TestTargetClass(MediaPlayer.class)
-public class MediaPlayerTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
-
-    private static String TAG = "CtsMediaPlayerTest";
-    private static final int SLEEP_TIME = 1000;
-    private static final int LONG_SLEEP_TIME = 6000;
-    private final String mSourceMediaOnSdcard;
-    private Monitor mOnVideoSizeChangedCalled = new Monitor();
-    private Monitor mOnBufferingUpdateCalled = new Monitor();
-    private Monitor mOnPrepareCalled = new Monitor();
-    private Monitor mOnSeekCompleteCalled = new Monitor();
-    private Monitor mOnCompletionCalled = new Monitor();
-    private Monitor mOnInfoCalled = new Monitor();
-    private Monitor mOnErrorCalled = new Monitor();
-    private Context mContext;
-    private Resources mResources;
-    private CtsTestServer mServer;
-    private static Object sVideoSizeChanged;
-    private static Object sLock;
-    private static Looper sLooper = null;
-    private static final int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
-
-    /*
-     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
-     * for the current thread. However, since we don't actually call loop() in the test,
-     * any messages queued with that looper will never be consumed. We instantiate the player
-     * in the constructor, before setUp(), so that its constructor does not see the
-     * nonfunctional Looper.
-     */
-    private MediaPlayer mMediaPlayer = new MediaPlayer();
-
-    static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
-        new MediaPlayer.OnVideoSizeChangedListener() {
-            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
-                synchronized (sVideoSizeChanged) {
-                    Log.v(TAG, "sizechanged notification received ...");
-                    sVideoSizeChanged.notify();
-                }
-            }
-        };
-
-    private static class Monitor {
-        private boolean signalled;
-
-        public synchronized void reset() {
-            signalled = false;
-        }
-
-        public synchronized void signal() {
-            signalled = true;
-            notifyAll();
-        }
-
-        public synchronized void waitForSignal() throws InterruptedException {
-            while (!signalled) {
-                wait();
-            }
+/**
+ * Tests for the MediaPlayer API and local video/audio playback.
+ *
+ * The files in res/raw used by testLocalVideo* are (c) copyright 2008,
+ * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
+ * 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);
+            fail("Null URI was accepted");
+        } catch (IllegalArgumentException e) {
+            // expected
         }
     }
 
-    public MediaPlayerTest() {
-        super("com.android.cts.stub", MediaStubActivity.class);
-        mSourceMediaOnSdcard = new File(Environment.getExternalStorageDirectory(),
-                                        "record_and_play.3gp").getAbsolutePath();
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mContext = getInstrumentation().getTargetContext();
-        mResources = mContext.getResources();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mMediaPlayer != null) {
-            mMediaPlayer.release();
-        }
-        File file = new File(mSourceMediaOnSdcard);
-        if (file.exists()) {
-            file.delete();
-        }
-        if (mServer != null) {
-            mServer.shutdown();
-        }
-        super.tearDown();
-    }
-
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "create",
-            args = {Context.class, int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setAudioStreamType",
-            args = {int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setWakeMode",
-            args = {Context.class, int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "isPlaying",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "start",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setLooping",
-            args = {boolean.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "isLooping",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getCurrentPosition",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "seekTo",
-            args = {int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "pause",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "stop",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "reset",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {FileDescriptor.class, long.class, long.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "prepare",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getDuration",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "release",
-            args = {}
-        )
-    })
     public void testPlayAudio() throws Exception {
         final int mp3Duration = 34909;
         final int tolerance = 70;
@@ -223,361 +51,266 @@
         final int resid = R.raw.testmp3_2;
 
         MediaPlayer mp = MediaPlayer.create(mContext, resid);
-        mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+        try {
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
 
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-        assertFalse(mp.isLooping());
-        mp.setLooping(true);
-        assertTrue(mp.isLooping());
+            assertFalse(mp.isLooping());
+            mp.setLooping(true);
+            assertTrue(mp.isLooping());
 
-        assertEquals(mp3Duration, mp.getDuration(), tolerance);
-        int pos = mp.getCurrentPosition();
-        assertTrue(pos >= 0);
-        assertTrue(pos < mp3Duration - seekDuration);
+            assertEquals(mp3Duration, mp.getDuration(), tolerance);
+            int pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < mp3Duration - seekDuration);
 
-        mp.seekTo(pos + seekDuration);
-        assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+            mp.seekTo(pos + seekDuration);
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
 
-        // test pause and restart
-        mp.pause();
-        Thread.sleep(SLEEP_TIME);
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
-
-        // test stop and restart
-        mp.stop();
-        mp.reset();
-        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
-        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        afd.close();
-        mp.prepare();
-        assertFalse(mp.isPlaying());
-        mp.start();
-        assertTrue(mp.isPlaying());
-
-        // waiting to complete
-        while(mp.isPlaying()) {
+            // test pause and restart
+            mp.pause();
             Thread.sleep(SLEEP_TIME);
-        }
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-        mp.release();
-    }
+            // test stop and restart
+            mp.stop();
+            mp.reset();
+            AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+            afd.close();
+            mp.prepare();
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "MediaPlayer",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDisplay",
-            args = {SurfaceHolder.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setScreenOnWhilePlaying",
-            args = {boolean.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getVideoHeight",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getVideoWidth",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setVolume",
-            args = {float.class, float.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {FileDescriptor.class}
-        )
-    })
-
-    /*
-     * Initializes the message looper so that the mediaPlayer object can
-     * receive the callback messages.
-     */
-    private static void initializeMessageLooper() {
-        new Thread() {
-            @Override
-            public void run() {
-                // Set up a looper to be used by camera.
-                Looper.prepare();
-                // Save the looper so that we can terminate this thread
-                // after we are done with it.
-                sLooper = Looper.myLooper();
-                synchronized (sLock) {
-                    sLock.notify();
-                }
-                Looper.loop();  // Blocks forever until Looper.quit() is called.
-                Log.v(TAG, "initializeMessageLooper: quit.");
+            // waiting to complete
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
             }
-        }.start();
-    }
-
-    /*
-     * Terminates the message looper thread.
-     */
-    private static void terminateMessageLooper() {
-        sLooper.quit();
+        } finally {
+            mp.release();
+        }
     }
 
     public void testPlayVideo() throws Exception {
-        final int expectedVideoWidth = 352; // width of R.raw.testvideo
-        final int expectedVideoHeight = 288; // height of R.raw.testvideo
-        final float leftVolume = 0.5f;
-        final float rightVolume = 0.5f;
-        final int resid = R.raw.testvideo;
-
-        sLock = new Object();
-        sVideoSizeChanged = new Object();
-        MediaPlayer mp = new MediaPlayer();
-        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
-        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        afd.close();
-        mp.setDisplay(getActivity().getSurfaceHolder());
-        mp.setScreenOnWhilePlaying(true);
-        mp.prepare();
-
-        int videoWidth = 0;
-        int videoHeight = 0;
-        synchronized (sLock) {
-            initializeMessageLooper();
-            try {
-                sLock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-            } catch(Exception e) {
-                Log.v(TAG, "looper was interrupted.");
-                return;
-            }
-        }
-        try {
-             mp.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
-             synchronized (sVideoSizeChanged) {
-                 try {
-                     sVideoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
-                 } catch (Exception e) {
-                     Log.v(TAG, "wait was interrupted");
-                 }
-             }
-             videoWidth = mp.getVideoWidth();
-             videoHeight = mp.getVideoHeight();
-             terminateMessageLooper();
-        } catch (Exception e) {
-             Log.e(TAG, e.getMessage());
-        }
-        assertEquals(expectedVideoWidth, videoWidth);
-        assertEquals(expectedVideoHeight, videoHeight);
-
-        mp.start();
-        mp.setVolume(leftVolume, rightVolume);
-
-        // waiting to complete
-        while (mp.isPlaying()) {
-            Thread.sleep(SLEEP_TIME);
-        }
-
-        mp.release();
+        playVideoTest(R.raw.testvideo, 352, 288);
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnBufferingUpdateListener",
-            args = {OnBufferingUpdateListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {String.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDisplay",
-            args = {SurfaceHolder.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "start",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "stop",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "prepare",
-            args = {}
-        )
-    })
-
-    public void testPlayMp3Stream1() throws Throwable {
-        streamTest("ringer.mp3", false, false);
-    }
-    public void testPlayMp3Stream2() throws Throwable {
-        streamTest("ringer.mp3", false, false);
-    }
-    public void testPlayMp3StreamRedirect() throws Throwable {
-        streamTest("ringer.mp3", true, false);
-    }
-    public void testPlayMp3StreamNoLength() throws Throwable {
-        streamTest("noiseandchirps.mp3", false, true);
-    }
-    public void testPlayOggStream() throws Throwable {
-        streamTest("noiseandchirps.ogg", false, false);
-    }
-    public void testPlayOggStreamRedirect() throws Throwable {
-        streamTest("noiseandchirps.ogg", true, false);
-    }
-    public void testPlayOggStreamNoLength() throws Throwable {
-        streamTest("noiseandchirps.ogg", false, true);
+    public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_500kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
     }
 
-    private void streamTest(String name, boolean redirect, boolean nolength) throws Throwable {
-        mServer = new CtsTestServer(mContext);
-        String stream_url = null;
-        if (redirect) {
-            // Stagefright doesn't have a limit, but we can't test support of infinite redirects
-            // Up to 4 redirects seems reasonable though.
-            stream_url = mServer.getRedirectingAssetUrl(name, 4);
-        } else {
-            stream_url = mServer.getAssetUrl(name);
-        }
-        if (nolength) {
-            stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
-        }
-
-        mMediaPlayer.setDataSource(stream_url);
-
-        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
-        mMediaPlayer.setScreenOnWhilePlaying(true);
-
-        mOnBufferingUpdateCalled.reset();
-        mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
-            public void onBufferingUpdate(MediaPlayer mp, int percent) {
-                mOnBufferingUpdateCalled.signal();
-            }
-        });
-
-        assertFalse(mOnBufferingUpdateCalled.signalled);
-        mMediaPlayer.prepare();
-
-        if (nolength) {
-            mMediaPlayer.start();
-            Thread.sleep(LONG_SLEEP_TIME);
-            assertFalse(mMediaPlayer.isPlaying());
-        } else {
-            mOnBufferingUpdateCalled.waitForSignal();
-            mMediaPlayer.start();
-            Thread.sleep(SLEEP_TIME);
-        }
-        mMediaPlayer.stop();
-        mMediaPlayer.reset();
+    public void testLocalVideo_MP4_H264_480x360_500kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnCompletionListener",
-            args = {OnCompletionListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnErrorListener",
-            args = {OnErrorListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnPreparedListener",
-            args = {OnPreparedListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnSeekCompleteListener",
-            args = {OnSeekCompleteListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnVideoSizeChangedListener",
-            args = {OnVideoSizeChangedListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setOnInfoListener",
-            args = {MediaPlayer.OnInfoListener.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {FileDescriptor.class, long.class, long.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "prepare",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "start",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "stop",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "isPlaying",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "seekTo",
-            args = {int.class}
-        )
-    })
+    public void testLocalVideo_MP4_H264_480x360_1000kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1000kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1000kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_25fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_25fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz, 480, 360);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_12fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_56kbps_25fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_56kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_12fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Mono_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_mono_24kbps_22050hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_24kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_24kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_11025Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
+    public void testLocalVideo_3gp_H263_176x144_300kbps_25fps_AAC_Stereo_128kbps_22050Hz()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, 176, 144);
+    }
+
     public void testCallback() throws Throwable {
         final int mp4Duration = 8484;
 
-        AssetFileDescriptor afd = mResources.openRawResourceFd(R.raw.testvideo);
-        try {
-            mMediaPlayer.setDataSource(
-                    afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-        } finally {
-            afd.close();
-        }
-
+        loadResource(R.raw.testvideo);
         mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
         mMediaPlayer.setScreenOnWhilePlaying(true);
 
         mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
+            @Override
             public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                 mOnVideoSizeChangedCalled.signal();
             }
         });
 
         mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+            @Override
             public void onPrepared(MediaPlayer mp) {
                 mOnPrepareCalled.signal();
             }
         });
 
         mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
+            @Override
             public void onSeekComplete(MediaPlayer mp) {
                 mOnSeekCompleteCalled.signal();
             }
@@ -585,12 +318,14 @@
 
         mOnCompletionCalled.reset();
         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+            @Override
             public void onCompletion(MediaPlayer mp) {
                 mOnCompletionCalled.signal();
             }
         });
 
         mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+            @Override
             public boolean onError(MediaPlayer mp, int what, int extra) {
                 mOnErrorCalled.signal();
                 return false;
@@ -598,83 +333,81 @@
         });
 
         mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
             public boolean onInfo(MediaPlayer mp, int what, int extra) {
                 mOnInfoCalled.signal();
                 return false;
             }
         });
 
-        assertFalse(mOnPrepareCalled.signalled);
-        assertFalse(mOnVideoSizeChangedCalled.signalled);
+        assertFalse(mOnPrepareCalled.isSignalled());
+        assertFalse(mOnVideoSizeChangedCalled.isSignalled());
         mMediaPlayer.prepare();
         mOnPrepareCalled.waitForSignal();
         mOnVideoSizeChangedCalled.waitForSignal();
-        mOnSeekCompleteCalled.signalled = false;
+        mOnSeekCompleteCalled.reset();
         mMediaPlayer.seekTo(mp4Duration >> 1);
         mOnSeekCompleteCalled.waitForSignal();
-        assertFalse(mOnCompletionCalled.signalled);
+        assertFalse(mOnCompletionCalled.isSignalled());
         mMediaPlayer.start();
         while(mMediaPlayer.isPlaying()) {
             Thread.sleep(SLEEP_TIME);
         }
         assertFalse(mMediaPlayer.isPlaying());
         mOnCompletionCalled.waitForSignal();
-        assertFalse(mOnErrorCalled.signalled);
+        assertFalse(mOnErrorCalled.isSignalled());
         mMediaPlayer.stop();
         mMediaPlayer.start();
         mOnErrorCalled.waitForSignal();
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {Context.class, Uri.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setDataSource",
-            args = {String.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "create",
-            args = {Context.class, Uri.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "create",
-            args = {Context.class, Uri.class, SurfaceHolder.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.PARTIAL,
-            method = "prepareAsync",
-            args = {}
-        )
-    })
     public void testRecordAndPlay() throws Exception {
-        recordMedia();
-        MediaPlayer mp = new MediaPlayer();
-        mp.setDataSource(mSourceMediaOnSdcard);
-        mp.prepareAsync();
-        Thread.sleep(SLEEP_TIME);
-        playAndStop(mp);
-        mp.reset();
-        Uri uri = Uri.parse(mSourceMediaOnSdcard);
-        mp = new MediaPlayer();
-        mp.setDataSource(mContext, uri);
-        mp.prepareAsync();
-        Thread.sleep(SLEEP_TIME);
-        playAndStop(mp);
-        mp.release();
+        File outputFile = new File(Environment.getExternalStorageDirectory(),
+                "record_and_play.3gp");
+        String outputFileLocation = outputFile.getAbsolutePath();
+        try {
+            recordMedia(outputFileLocation);
+            MediaPlayer mp = new MediaPlayer();
+            try {
+                mp.setDataSource(outputFileLocation);
+                mp.prepareAsync();
+                Thread.sleep(SLEEP_TIME);
+                playAndStop(mp);
+            } finally {
+                mp.release();
+            }
 
-        mp = MediaPlayer.create(mContext, uri);
-        playAndStop(mp);
-        mp.release();
+            Uri uri = Uri.parse(outputFileLocation);
+            mp = new MediaPlayer();
+            try {
+                mp.setDataSource(mContext, uri);
+                mp.prepareAsync();
+                Thread.sleep(SLEEP_TIME);
+                playAndStop(mp);
+            } finally {
+                mp.release();
+            }
 
-        mp = MediaPlayer.create(mContext, uri, getActivity().getSurfaceHolder());
-        playAndStop(mp);
-        mp.release();
+            try {
+                mp = MediaPlayer.create(mContext, uri);
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.release();
+                }
+            }
+
+            try {
+                mp = MediaPlayer.create(mContext, uri, getActivity().getSurfaceHolder());
+                playAndStop(mp);
+            } finally {
+                if (mp != null) {
+                    mp.release();
+                }
+            }
+        } finally {
+            outputFile.delete();
+        }
     }
 
     private void playAndStop(MediaPlayer mp) throws Exception {
@@ -683,18 +416,20 @@
         mp.stop();
     }
 
-    private void recordMedia() throws Exception {
+    private void recordMedia(String outputFile) throws Exception {
         MediaRecorder mr = new MediaRecorder();
-        mr.setAudioSource(MediaRecorder.AudioSource.MIC);
-        mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
-        mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
-        mr.setOutputFile(mSourceMediaOnSdcard);
+        try {
+            mr.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
+            mr.setOutputFile(outputFile);
 
-        mr.prepare();
-        mr.start();
-        Thread.sleep(SLEEP_TIME);
-        mr.stop();
-        mr.release();
+            mr.prepare();
+            mr.start();
+            Thread.sleep(SLEEP_TIME);
+            mr.stop();
+        } finally {
+            mr.release();
+        }
     }
-
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
new file mode 100644
index 0000000..660b539
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -0,0 +1,136 @@
+/*
+ * 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.media.cts;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.media.MediaPlayer;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Base class for tests which use MediaPlayer to play audio or video.
+ */
+public class MediaPlayerTestBase extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+    protected static final int SLEEP_TIME = 1000;
+    protected static final int LONG_SLEEP_TIME = 6000;
+
+    public static class Monitor {
+        private boolean signalled;
+
+        public synchronized void reset() {
+            signalled = false;
+        }
+
+        public synchronized void signal() {
+            signalled = true;
+            notifyAll();
+        }
+
+        public synchronized void waitForSignal() throws InterruptedException {
+            while (!signalled) {
+                wait();
+            }
+        }
+
+        public synchronized boolean isSignalled() {
+            return signalled;
+        }
+    }
+
+    protected Monitor mOnVideoSizeChangedCalled = new Monitor();
+    protected Monitor mOnBufferingUpdateCalled = new Monitor();
+    protected Monitor mOnPrepareCalled = new Monitor();
+    protected Monitor mOnSeekCompleteCalled = new Monitor();
+    protected Monitor mOnCompletionCalled = new Monitor();
+    protected Monitor mOnInfoCalled = new Monitor();
+    protected Monitor mOnErrorCalled = new Monitor();
+
+    protected Context mContext;
+    protected Resources mResources;
+
+    /*
+     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
+     * for the current thread. However, since we don't actually call loop() in the test,
+     * any messages queued with that looper will never be consumed. We instantiate the player
+     * in the constructor, before setUp(), so that its constructor does not see the
+     * nonfunctional Looper.
+     */
+    protected MediaPlayer mMediaPlayer = new MediaPlayer();
+
+    public MediaPlayerTestBase() {
+        super(MediaStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        mResources = mContext.getResources();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.release();
+        }
+        super.tearDown();
+    }
+
+    protected void loadResource(int resid) throws Exception {
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                    afd.getLength());
+        } finally {
+            afd.close();
+        }
+    }
+
+    protected void playVideoTest(int resid, final int width, final int height) throws Exception {
+        final float leftVolume = 0.5f;
+        final float rightVolume = 0.5f;
+
+        loadResource(resid);
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
+            @Override
+            public void onVideoSizeChanged(MediaPlayer mp, int w, int h) {
+                mOnVideoSizeChangedCalled.signal();
+                assertEquals(width, w);
+                assertEquals(height, h);
+            }
+        });
+        mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+            @Override
+            public boolean onError(MediaPlayer mp, int what, int extra) {
+                fail("Media player had error " + what + " playing video");
+                return true;
+            }
+        });
+        mMediaPlayer.prepare();
+        mOnVideoSizeChangedCalled.waitForSignal();
+
+        mMediaPlayer.start();
+        mMediaPlayer.setVolume(leftVolume, rightVolume);
+
+        // waiting to complete
+        while (mMediaPlayer.isPlaying()) {
+            Thread.sleep(SLEEP_TIME);
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index ee0b025..1962f59 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -150,6 +150,9 @@
         )
     })
     public void testRecorderCamera() throws Exception {
+        if (Camera.getNumberOfCameras() < 1) {
+            return;
+        }
         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
         mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
@@ -262,6 +265,9 @@
         )
     })
     public void testRecorderVideo() throws Exception {
+        if (Camera.getNumberOfCameras() < 1) {
+            return;
+        }
         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
         mMediaRecorder.setOutputFile(OUTPUT_PATH2);
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
old mode 100644
new mode 100755
index 7b56b56..7ea9612
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -83,7 +83,9 @@
                     "302720",   // Rogers
                     "30272",    // Rogers
                     "302370",   // Fido
-                    "30237"     // Fido
+                    "30237",    // Fido
+                    "311490",   // Virgin Mobile
+                    "310000"    // Tracfone
             );
 
     // List of network operators that doesn't support Data(binary) SMS message
@@ -94,7 +96,8 @@
                     "302720",   // Rogers
                     "30272",    // Rogers
                     "302370",   // Fido
-                    "30237"     // Fido
+                    "30237",     // Fido
+                    "45008"     // KT
             );
 
     // List of network operators that doesn't support Maltipart SMS message
diff --git a/tests/tests/view/src/android/view/cts/GestureDetectorTestUtil.java b/tests/tests/view/src/android/view/cts/GestureDetectorTestUtil.java
index ff4fe5a..b43c8e2 100644
--- a/tests/tests/view/src/android/view/cts/GestureDetectorTestUtil.java
+++ b/tests/tests/view/src/android/view/cts/GestureDetectorTestUtil.java
@@ -16,9 +16,11 @@
 
 package android.view.cts;
 
+import android.graphics.Rect;
 import android.test.InstrumentationTestCase;
 import android.test.TouchUtils;
 import android.view.View;
+import android.view.Window;
 
 class GestureDetectorTestUtil {
 
@@ -34,11 +36,18 @@
         TouchUtils.longClickView(testcase, view);
         TouchUtils.scrollToBottom(testcase, activity, activity.getViewGroup());
         TouchUtils.touchAndCancelView(testcase, view);
+
+        Rect windowRect = new Rect();
+        Window window = activity.getWindow();
+        window.getDecorView().getWindowVisibleDisplayFrame(windowRect);
+        int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
+        int statusBarHeight = contentViewTop - windowRect.top;
+
         int fromX = 1;
         int toX = 10;
         // Y has to be outside the status bar bounding box
-        int fromY = 50;
-        int toY = 100;
+        int fromY = statusBarHeight + 1;
+        int toY = statusBarHeight + 51;
         int stepCount = 20;
         TouchUtils.drag(testcase, fromX, toX, fromY, toY, stepCount);
         InstrumentationTestCase.assertTrue(activity.isDown);
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
old mode 100644
new mode 100755
index 2131965..6bd094f
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -312,7 +312,7 @@
         mGridView = findGridViewById(R.id.gridview);
         // Number of columns should be big enough, otherwise the
         // horizontal spacing cannot be correctly verified.
-        mGridView.setNumColumns(20);
+        mGridView.setNumColumns(22);
 
         // this test case can not be ran in UI thread.
         mActivity.runOnUiThread(new Runnable() {