am 7315af87: Need enough time (1 sec) to read amounts of packet from /proc/stat_uid/[uid]/tcp_snd.

Merge commit '7315af875fa2e7c6159d4a771518a37373b0c139' into gingerbread

* commit '7315af875fa2e7c6159d4a771518a37373b0c139':
  Need enough time (1 sec) to read amounts of packet from /proc/stat_uid/[uid]/tcp_snd.
diff --git a/.gitignore b/.gitignore
index 542ab17..ca65e7d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 *.pyc
 *.~*
+bin
diff --git a/tests/ProcessTest/Android.mk b/tests/ProcessTest/Android.mk
index be1e7de..ba58e87 100644
--- a/tests/ProcessTest/Android.mk
+++ b/tests/ProcessTest/Android.mk
@@ -20,7 +20,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := framework-tests android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_AAPT_FLAGS = -c xx_YY -c cs
 
diff --git a/tests/appsecurity-tests/src/com/android/cts/appsecurity/AppSecurityTests.java b/tests/appsecurity-tests/src/com/android/cts/appsecurity/AppSecurityTests.java
index f528ee1..2833fa4 100644
--- a/tests/appsecurity-tests/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ b/tests/appsecurity-tests/src/com/android/cts/appsecurity/AppSecurityTests.java
@@ -225,8 +225,9 @@
      *
      * @param pkgName Android application package for tests
      * @return <code>true</code> if all tests passed.
+     * @throws IOException if connection to device was lost
      */
-    private boolean runDeviceTests(String pkgName) {
+    private boolean runDeviceTests(String pkgName) throws IOException {
         CollectingTestRunListener listener = doRunTests(pkgName);
         return listener.didAllTestsPass();
     }
@@ -235,8 +236,9 @@
      * Helper method to run tests and return the listener that collected the results.
      * @param pkgName Android application package for tests
      * @return the {@link CollectingTestRunListener}
+     * @throws IOException if connection to device was lost
      */
-    private CollectingTestRunListener doRunTests(String pkgName) {
+    private CollectingTestRunListener doRunTests(String pkgName) throws IOException {
         RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName, getDevice());
         CollectingTestRunListener listener = new CollectingTestRunListener();
         testRunner.run(listener);
diff --git a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/AndroidManifest.xml b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/AndroidManifest.xml
index 53ab2cf..b8b8ce6 100644
--- a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/AndroidManifest.xml
+++ b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/AndroidManifest.xml
@@ -24,12 +24,42 @@
     <permission android:name="com.android.cts.permissionWithSignature"
         android:protectionLevel="signature" />
 
+    <uses-permission android:name="com.android.cts.permissionWithSignature" />
+
     <application>
+        <receiver android:name="GrantUriPermission" android:exported="true">
+        </receiver>
+
         <!-- Need a way for another app to try to access the permission. So create a content
         provider which is enforced by the permission -->
         <provider android:name="PermissionContentProvider"
                 android:authorities="ctspermissionwithsignature"
                 android:readPermission="com.android.cts.permissionWithSignature"
-                android:writePermission="com.android.cts.permissionWithSignature" />
+                android:writePermission="com.android.cts.permissionWithSignature">
+            <grant-uri-permission android:pathPattern=".*" />
+        </provider>
+
+        <!-- Need a way for another app to try to access the permission, but will
+             grant uri access. -->
+        <provider android:name="PermissionContentProviderGranting"
+                android:authorities="ctspermissionwithsignaturegranting"
+                android:readPermission="com.android.cts.permissionWithSignature"
+                android:writePermission="com.android.cts.permissionWithSignature">
+            <grant-uri-permission android:pathPattern=".*" />
+        </provider>
+
+        <!-- Nobody else should get access to this -->
+        <provider android:name="PrivateContentProvider"
+                android:authorities="ctsprivateprovider"
+                android:exported="false">
+            <grant-uri-permission android:pathPattern=".*" />
+        </provider>
+
+        <!-- Nobody else should get access to this, but we will grant uri access -->
+        <provider android:name="PrivateContentProviderGranting"
+                android:authorities="ctsprivateprovidergranting"
+                android:exported="false">
+            <grant-uri-permission android:pathPattern=".*" />
+        </provider>
     </application>
 </manifest>
diff --git a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/GrantUriPermission.java b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/GrantUriPermission.java
new file mode 100644
index 0000000..3322f45
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/GrantUriPermission.java
@@ -0,0 +1,19 @@
+package com.android.cts.permissiondeclareapp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class GrantUriPermission extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Intent newIntent = (Intent)intent.getParcelableExtra("intent");
+        boolean service = intent.getBooleanExtra("service", false);
+        if (!service) {
+            newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(newIntent);
+        } else {
+            context.startService(newIntent);
+        }
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
new file mode 100644
index 0000000..46b1b3e
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.permissiondeclareapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class PermissionContentProviderGranting extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
new file mode 100644
index 0000000..dfbdbb7
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.permissiondeclareapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class PrivateContentProvider extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
new file mode 100644
index 0000000..f81c27a
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.permissiondeclareapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class PrivateContentProviderGranting extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/AndroidManifest.xml b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/AndroidManifest.xml
index b915ebc..d86fcc5 100644
--- a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/AndroidManifest.xml
+++ b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/AndroidManifest.xml
@@ -25,6 +25,9 @@
 
     <application>
         <uses-library android:name="android.test.runner"/>
+        <activity android:name=".ReceiveUriActivity" android:exported="true"
+                android:launchMode="singleTop" />
+        <service android:name=".ReceiveUriService" android:exported="true" />
     </application>
 
     <instrumentation android:targetPackage="com.android.cts.usespermissiondiffcertapp"
diff --git a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index 510d5e4..da43665 100644
--- a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -16,21 +16,534 @@
 
 package com.android.cts.usespermissiondiffcertapp;
 
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Intent;
 import android.net.Uri;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 /**
  * Tests that signature-enforced permissions cannot be accessed by apps signed
  * with different certs than app that declares the permission.
  */
 public class AccessPermissionWithDiffSigTest extends AndroidTestCase {
+    static final ComponentName GRANT_URI_PERM_COMP
+            = new ComponentName("com.android.cts.permissiondeclareapp",
+                    "com.android.cts.permissiondeclareapp.GrantUriPermission");
+    static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
+    static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
+    static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
+    static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
+
+    public void assertReadingContentUriNotAllowed(Uri uri, String msg) {
+        try {
+            getContext().getContentResolver().query(uri, null, null, null, null);
+            fail("expected SecurityException reading " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+    }
+
+    public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+        try {
+            getContext().getContentResolver().insert(uri, new ContentValues());
+            fail("expected SecurityException writing " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+    }
 
     /**
      * Test that the ctspermissionwithsignature content provider cannot be read,
      * since this app lacks the required certs
      */
     public void testReadProviderWithDiff() {
-        assertReadingContentUriRequiresPermission(Uri.parse("content://ctspermissionwithsignature"),
+        assertReadingContentUriRequiresPermission(PERM_URI,
                 "com.android.cts.permissionWithSignature");
     }
+
+    /**
+     * Test that the ctspermissionwithsignature content provider cannot be written,
+     * since this app lacks the required certs
+     */
+    public void testWriteProviderWithDiff() {
+        assertWritingContentUriRequiresPermission(PERM_URI,
+                "com.android.cts.permissionWithSignature");
+    }
+
+    /**
+     * Test that the ctsprivateprovider content provider cannot be read,
+     * since it is not exported from its app.
+     */
+    public void testReadProviderWhenPrivate() {
+        assertReadingContentUriNotAllowed(PRIV_URI,
+                "shouldn't read private provider");
+    }
+
+    /**
+     * Test that the ctsprivateprovider content provider cannot be written,
+     * since it is not exported from its app.
+     */
+    public void testWriteProviderWhenPrivate() {
+        assertWritingContentUriNotAllowed(PRIV_URI,
+                "shouldn't write private provider");
+    }
+
+    public void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
+        Intent grantIntent = new Intent();
+        grantIntent.setData(uri);
+        grantIntent.addFlags(mode | Intent.FLAG_ACTIVITY_NEW_TASK);
+        grantIntent.setClass(getContext(), ReceiveUriActivity.class);
+        try {
+            ReceiveUriActivity.clearStarted();
+            getContext().startActivity(grantIntent);
+            ReceiveUriActivity.waitForStart();
+            fail("expected SecurityException granting " + uri + " to activity");
+        } catch (SecurityException e) {
+            // This is what we want.
+        }
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantReadUriActivityPermissionToSelf() {
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantWriteUriActivityPermissionToSelf() {
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantReadUriActivityPrivateToSelf() {
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantWriteUriActivityPrivateToSelf() {
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    public void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
+        Intent grantIntent = new Intent();
+        grantIntent.setData(uri);
+        grantIntent.addFlags(mode);
+        grantIntent.setClass(getContext(), ReceiveUriService.class);
+        try {
+            getContext().startService(grantIntent);
+            fail("expected SecurityException granting " + uri + " to service");
+        } catch (SecurityException e) {
+            // This is what we want.
+        }
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantReadUriServicePermissionToSelf() {
+        doTryGrantUriServicePermissionToSelf(
+                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantWriteUriServicePermissionToSelf() {
+        doTryGrantUriServicePermissionToSelf(
+                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantReadUriServicePrivateToSelf() {
+        doTryGrantUriServicePermissionToSelf(
+                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+    }
+
+    /**
+     * Test that we can't grant a permission to ourself.
+     */
+    public void testGrantWriteUriServicePrivateToSelf() {
+        doTryGrantUriServicePermissionToSelf(
+                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+    }
+
+    void grantUriPermission(Uri uri, int mode, boolean service) {
+        Intent grantIntent = new Intent();
+        grantIntent.setData(uri);
+        grantIntent.addFlags(mode);
+        grantIntent.setClass(getContext(),
+                service ? ReceiveUriService.class : ReceiveUriActivity.class);
+        Intent intent = new Intent();
+        intent.setComponent(GRANT_URI_PERM_COMP);
+        intent.putExtra("intent", grantIntent);
+        intent.putExtra("service", service);
+        getContext().sendBroadcast(intent);
+    }
+
+    void doTestGrantActivityUriReadPermission(Uri uri) {
+        final Uri subUri = Uri.withAppendedPath(uri, "foo");
+        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
+        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
+        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
+
+        // Precondition: no current access.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read when starting test");
+        assertReadingContentUriNotAllowed(sub2Uri, "shouldn't read when starting test");
+
+        ReceiveUriActivity.clearStarted();
+        grantUriPermission(subUri, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForStart();
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().query(subUri, null, null, null, null);
+
+        // But not writing.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write from granted read");
+
+        // And not to the base path.
+        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
+
+        // And not to a sub path.
+        assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
+
+        // Dispose of activity.
+        ReceiveUriActivity.finishCurInstanceSync();
+
+        // Ensure reading no longer allowed.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read after losing granted URI");
+    }
+
+    void doTestGrantActivityUriWritePermission(Uri uri) {
+        final Uri subUri = Uri.withAppendedPath(uri, "foo");
+        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
+        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
+        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
+
+        // Precondition: no current access.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write when starting test");
+        assertWritingContentUriNotAllowed(sub2Uri, "shouldn't write when starting test");
+
+        // --------------------------------
+
+        ReceiveUriActivity.clearStarted();
+        grantUriPermission(subUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForStart();
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().insert(subUri, new ContentValues());
+
+        // But not reading.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read from granted write");
+
+        // And not to the base path.
+        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
+
+        // And not a sub-path.
+        assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
+
+        // --------------------------------
+
+        ReceiveUriActivity.clearNewIntent();
+        grantUriPermission(sub2Uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForNewIntent();
+
+        if (false) {
+            synchronized (this) {
+                Log.i("**", "******************************* WAITING!!!");
+                try {
+                    wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().insert(sub2Uri, new ContentValues());
+
+        // And still have access to the original URI.
+        getContext().getContentResolver().insert(subUri, new ContentValues());
+
+        // But not reading.
+        assertReadingContentUriNotAllowed(sub2Uri, "shouldn't read from granted write");
+
+        // And not to the base path.
+        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
+
+        // And not a sub-path.
+        assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
+
+        // And make sure we can't generate a permission to a running activity.
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(uri, "hah"),
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        doTryGrantUriActivityPermissionToSelf(
+                Uri.withAppendedPath(uri, "hah"),
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        // --------------------------------
+
+        // Dispose of activity.
+        ReceiveUriActivity.finishCurInstanceSync();
+
+        if (false) {
+            synchronized (this) {
+                Log.i("**", "******************************* WAITING!!!");
+                try {
+                    wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        // Ensure writing no longer allowed.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write after losing granted URI");
+        assertWritingContentUriNotAllowed(sub2Uri, "shouldn't write after losing granted URI");
+    }
+
+    /**
+     * Test that the ctspermissionwithsignaturegranting content provider can grant a read
+     * permission.
+     */
+    public void testGrantActivityReadPermissionFromStartActivity() {
+        doTestGrantActivityUriReadPermission(PERM_URI_GRANTING);
+    }
+
+    /**
+     * Test that the ctspermissionwithsignaturegranting content provider can grant a write
+     * permission.
+     */
+    public void testGrantActivityWritePermissionFromStartActivity() {
+        doTestGrantActivityUriWritePermission(PERM_URI_GRANTING);
+    }
+
+    /**
+     * Test that the ctsprivateprovidergranting content provider can grant a read
+     * permission.
+     */
+    public void testGrantActivityReadPrivateFromStartActivity() {
+        doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING);
+    }
+
+    /**
+     * Test that the ctsprivateprovidergranting content provider can grant a write
+     * permission.
+     */
+    public void testGrantActivityWritePrivateFromStartActivity() {
+        doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING);
+    }
+
+    void doTestGrantServiceUriReadPermission(Uri uri) {
+        final Uri subUri = Uri.withAppendedPath(uri, "foo");
+        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
+        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
+        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
+
+        ReceiveUriService.stop(getContext());
+
+        // Precondition: no current access.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read when starting test");
+        assertReadingContentUriNotAllowed(sub2Uri, "shouldn't read when starting test");
+
+        // --------------------------------
+
+        ReceiveUriService.clearStarted();
+        grantUriPermission(subUri, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
+        ReceiveUriService.waitForStart();
+
+        int firstStartId = ReceiveUriService.getCurStartId();
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().query(subUri, null, null, null, null);
+
+        // But not writing.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write from granted read");
+
+        // And not to the base path.
+        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
+
+        // And not to a sub path.
+        assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
+
+        // --------------------------------
+
+        // Send another Intent to it.
+        ReceiveUriService.clearStarted();
+        grantUriPermission(sub2Uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
+        ReceiveUriService.waitForStart();
+
+        if (false) {
+            synchronized (this) {
+                Log.i("**", "******************************* WAITING!!!");
+                try {
+                    wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().query(sub2Uri, null, null, null, null);
+
+        // And still to the previous URI.
+        getContext().getContentResolver().query(subUri, null, null, null, null);
+
+        // But not writing.
+        assertWritingContentUriNotAllowed(sub2Uri, "shouldn't write from granted read");
+
+        // And not to the base path.
+        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
+
+        // And not to a sub path.
+        assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");
+
+        // --------------------------------
+
+        // Stop the first command.
+        ReceiveUriService.stopCurWithId(firstStartId);
+
+        // Ensure reading no longer allowed.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read after losing granted URI");
+
+        // And make sure we can't generate a permission to a running service.
+        doTryGrantUriActivityPermissionToSelf(subUri,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        doTryGrantUriActivityPermissionToSelf(subUri,
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        // --------------------------------
+
+        // Dispose of service.
+        ReceiveUriService.stopSync(getContext());
+
+        // Ensure reading no longer allowed.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read after losing granted URI");
+        assertReadingContentUriNotAllowed(sub2Uri, "shouldn't read after losing granted URI");
+    }
+
+    void doTestGrantServiceUriWritePermission(Uri uri) {
+        final Uri subUri = Uri.withAppendedPath(uri, "foo");
+        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
+        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
+        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
+
+        ReceiveUriService.stop(getContext());
+
+        // Precondition: no current access.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write when starting test");
+        assertWritingContentUriNotAllowed(sub2Uri, "shouldn't write when starting test");
+
+        // --------------------------------
+
+        ReceiveUriService.clearStarted();
+        grantUriPermission(subUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
+        ReceiveUriService.waitForStart();
+
+        int firstStartId = ReceiveUriService.getCurStartId();
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().insert(subUri, new ContentValues());
+
+        // But not reading.
+        assertReadingContentUriNotAllowed(subUri, "shouldn't read from granted write");
+
+        // And not to the base path.
+        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
+
+        // And not a sub-path.
+        assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
+
+        // --------------------------------
+
+        // Send another Intent to it.
+        ReceiveUriService.clearStarted();
+        grantUriPermission(sub2Uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
+        ReceiveUriService.waitForStart();
+
+        // See if we now have access to the provider.
+        getContext().getContentResolver().insert(sub2Uri, new ContentValues());
+
+        // And still to the previous URI.
+        getContext().getContentResolver().insert(subUri, new ContentValues());
+
+        // But not reading.
+        assertReadingContentUriNotAllowed(sub2Uri, "shouldn't read from granted write");
+
+        // And not to the base path.
+        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
+
+        // And not a sub-path.
+        assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
+
+        if (false) {
+            synchronized (this) {
+                Log.i("**", "******************************* WAITING!!!");
+                try {
+                    wait(10000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        // --------------------------------
+
+        // Stop the first command.
+        ReceiveUriService.stopCurWithId(firstStartId);
+
+        // Ensure writing no longer allowed.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write after losing granted URI");
+
+        // And make sure we can't generate a permission to a running service.
+        doTryGrantUriActivityPermissionToSelf(subUri,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        doTryGrantUriActivityPermissionToSelf(subUri,
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        // --------------------------------
+
+        // Dispose of service.
+        ReceiveUriService.stopSync(getContext());
+
+        // Ensure writing no longer allowed.
+        assertWritingContentUriNotAllowed(subUri, "shouldn't write after losing granted URI");
+        assertWritingContentUriNotAllowed(sub2Uri, "shouldn't write after losing granted URI");
+    }
+
+    public void testGrantActivityReadPermissionFromStartService() {
+        doTestGrantServiceUriReadPermission(PERM_URI_GRANTING);
+    }
+
+    public void testGrantActivityWritePermissionFromStartService() {
+        doTestGrantServiceUriWritePermission(PERM_URI_GRANTING);
+    }
+
+    public void testGrantActivityReadPrivateFromStartService() {
+        doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING);
+    }
+
+    public void testGrantActivityWritePrivateFromStartService() {
+        doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING);
+    }
 }
diff --git a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriActivity.java b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriActivity.java
new file mode 100644
index 0000000..c6a2386
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriActivity.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.usespermissiondiffcertapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.os.MessageQueue.IdleHandler;
+
+public class ReceiveUriActivity extends Activity {
+    private static final Object sLock = new Object();
+    private static boolean sStarted;
+    private static boolean sNewIntent;
+    private static boolean sDestroyed;
+    private static ReceiveUriActivity sCurInstance;
+
+    Handler mHandler = new Handler();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        synchronized (sLock) {
+            if (sCurInstance != null) {
+                finishCurInstance();
+            }
+            sCurInstance = this;
+            sStarted = true;
+            sDestroyed = false;
+            sLock.notifyAll();
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        synchronized (sLock) {
+            sNewIntent = true;
+            sLock.notifyAll();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        Looper.myQueue().addIdleHandler(new IdleHandler() {
+            @Override
+            public boolean queueIdle() {
+                synchronized (sLock) {
+                    sDestroyed = true;
+                    sLock.notifyAll();
+                }
+                return false;
+            }
+        });
+    }
+
+    public static void finishCurInstance() {
+        synchronized (sLock) {
+            if (sCurInstance != null) {
+                sCurInstance.finish();
+                sCurInstance = null;
+            }
+        }
+    }
+
+    public static void finishCurInstanceSync() {
+        finishCurInstance();
+
+        synchronized (sLock) {
+            final long startTime = SystemClock.uptimeMillis();
+            while (!sDestroyed) {
+                try {
+                    sLock.wait(5000);
+                } catch (InterruptedException e) {
+                }
+                if (SystemClock.uptimeMillis() >= (startTime+5000)) {
+                    throw new RuntimeException("Timeout");
+                }
+            }
+        }
+    }
+
+    public static void clearStarted() {
+        synchronized (sLock) {
+            sStarted = false;
+        }
+    }
+
+    public static void clearNewIntent() {
+        synchronized (sLock) {
+            sNewIntent = false;
+        }
+    }
+
+    public static void waitForStart() {
+        synchronized (sLock) {
+            final long startTime = SystemClock.uptimeMillis();
+            while (!sStarted) {
+                try {
+                    sLock.wait(5000);
+                } catch (InterruptedException e) {
+                }
+                if (SystemClock.uptimeMillis() >= (startTime+5000)) {
+                    throw new RuntimeException("Timeout");
+                }
+            }
+        }
+    }
+
+    public static void waitForNewIntent() {
+        synchronized (sLock) {
+            final long startTime = SystemClock.uptimeMillis();
+            while (!sNewIntent) {
+                try {
+                    sLock.wait(5000);
+                } catch (InterruptedException e) {
+                }
+                if (SystemClock.uptimeMillis() >= (startTime+5000)) {
+                    throw new RuntimeException("Timeout");
+                }
+            }
+        }
+    }
+}
diff --git a/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriService.java b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriService.java
new file mode 100644
index 0000000..68d78c0
--- /dev/null
+++ b/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/ReceiveUriService.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.usespermissiondiffcertapp;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.os.MessageQueue.IdleHandler;
+
+public class ReceiveUriService extends Service {
+    private static final Object sLock = new Object();
+    private static boolean sStarted;
+    private static boolean sDestroyed;
+    private static int sCurStartId;
+    private static ReceiveUriService sCurInstance;
+
+    Handler mHandler = new Handler();
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        synchronized (sLock) {
+            sCurStartId = startId;
+            sCurInstance = this;
+            sStarted = true;
+            sDestroyed = false;
+            sLock.notifyAll();
+        }
+
+        return START_REDELIVER_INTENT;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Looper.myQueue().addIdleHandler(new IdleHandler() {
+            @Override
+            public boolean queueIdle() {
+                synchronized (sLock) {
+                    sDestroyed = true;
+                    sCurInstance = null;
+                    sLock.notifyAll();
+                }
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    public static void stop(Context context) {
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName(
+                "com.android.cts.usespermissiondiffcertapp",
+                "com.android.cts.usespermissiondiffcertapp.ReceiveUriService"));
+        context.stopService(intent);
+    }
+
+    public static int getCurStartId() {
+        synchronized (sLock) {
+            return sCurStartId;
+        }
+    }
+
+    public static void stopCurWithId(int id) {
+        synchronized (sLock) {
+            sCurInstance.stopSelf(id);
+        }
+    }
+
+    public static void stopSync(Context context) {
+        stop(context);
+
+        synchronized (sLock) {
+            final long startTime = SystemClock.uptimeMillis();
+            while (!sDestroyed) {
+                try {
+                    sLock.wait(5000);
+                } catch (InterruptedException e) {
+                }
+                if (SystemClock.uptimeMillis() >= (startTime+5000)) {
+                    throw new RuntimeException("Timeout");
+                }
+            }
+        }
+    }
+
+    public static void clearStarted() {
+        synchronized (sLock) {
+            sStarted = false;
+        }
+    }
+
+    public static void waitForStart() {
+        synchronized (sLock) {
+            final long startTime = SystemClock.uptimeMillis();
+            while (!sStarted) {
+                try {
+                    sLock.wait(5000);
+                } catch (InterruptedException e) {
+                }
+                if (SystemClock.uptimeMillis() >= (startTime+5000)) {
+                    throw new RuntimeException("Timeout");
+                }
+            }
+        }
+    }
+}
diff --git a/tests/core/annotation/Android.mk b/tests/core/annotation/Android.mk
deleted file mode 100644
index 4778710..0000000
--- a/tests/core/annotation/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Annotation Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/annotation/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.annotation
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/annotation/AndroidManifest.xml b/tests/core/annotation/AndroidManifest.xml
deleted file mode 100644
index 7e34d2a..0000000
--- a/tests/core/annotation/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.annotation">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/archive/Android.mk b/tests/core/archive/Android.mk
deleted file mode 100644
index 78edd09..0000000
--- a/tests/core/archive/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Archive Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/archive/src/test/java/org) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.archive
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/archive/AndroidManifest.xml b/tests/core/archive/AndroidManifest.xml
deleted file mode 100644
index 22ba6f7..0000000
--- a/tests/core/archive/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.archive">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/concurrent/Android.mk b/tests/core/concurrent/Android.mk
deleted file mode 100644
index d42c6da..0000000
--- a/tests/core/concurrent/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Concurrent Tests
-##########################################################
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/concurrent/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.concurrent
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/concurrent/AndroidManifest.xml b/tests/core/concurrent/AndroidManifest.xml
deleted file mode 100644
index b3ee187..0000000
--- a/tests/core/concurrent/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.concurrent">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/crypto/Android.mk b/tests/core/crypto/Android.mk
deleted file mode 100644
index 2450ad1..0000000
--- a/tests/core/crypto/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# crypto Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/crypto/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java/) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.crypto
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/crypto/AndroidManifest.xml b/tests/core/crypto/AndroidManifest.xml
deleted file mode 100644
index 25052ee..0000000
--- a/tests/core/crypto/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.crypto">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/ctscore.mk b/tests/core/ctscore.mk
index 085730c..337b3f5 100644
--- a/tests/core/ctscore.mk
+++ b/tests/core/ctscore.mk
@@ -17,7 +17,7 @@
 # and when built explicitly put them in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
 
 LOCAL_PROGUARD_ENABLED := disabled
 
diff --git a/tests/core/dom/Android.mk b/tests/core/dom/Android.mk
index 47b3dbb..69d4af3 100644
--- a/tests/core/dom/Android.mk
+++ b/tests/core/dom/Android.mk
@@ -23,10 +23,13 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/dom/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := $(call all-java-files-under,../../../../libcore/dom/src/test/java) \
+	$(call all-java-files-under,../../../../libcore/junit/src/test/java/junit) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java/)
 
 LOCAL_PACKAGE_NAME := android.core.tests.dom
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/logging/Android.mk b/tests/core/logging/Android.mk
deleted file mode 100644
index 89d1ca9..0000000
--- a/tests/core/logging/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Logging Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/logging/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.logging
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/logging/AndroidManifest.xml b/tests/core/logging/AndroidManifest.xml
deleted file mode 100644
index c6e5bee..0000000
--- a/tests/core/logging/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.logging">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/luni-io/Android.mk b/tests/core/luni-io/Android.mk
index f2aae36..ed39e03 100644
--- a/tests/core/luni-io/Android.mk
+++ b/tests/core/luni-io/Android.mk
@@ -23,14 +23,16 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/tests/api/java/io) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java/) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/pkg1) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/pkg2) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/luni/AllTestsIo.java \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := $(call all-java-files-under,../../../../libcore/luni/src/test/java/tests/api/java/io) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java/) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/pkg1) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/pkg2) \
+	../../../../libcore/luni/src/test/java/tests/luni/AllTestsIo.java
 
 LOCAL_PACKAGE_NAME := android.core.tests.luni.io
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/luni-lang/Android.mk b/tests/core/luni-lang/Android.mk
index 225bdf9..a31b881 100644
--- a/tests/core/luni-lang/Android.mk
+++ b/tests/core/luni-lang/Android.mk
@@ -23,12 +23,14 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/tests/api/java/lang) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java/) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/luni/AllTestsLang.java \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := $(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/tests/api/java/lang) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java/) \
+	../../../../libcore/luni/src/test/java/tests/luni/AllTestsLang.java
 
 LOCAL_PACKAGE_NAME := android.core.tests.luni.lang
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/luni-net/Android.mk b/tests/core/luni-net/Android.mk
index 1092ff1..795ec87 100644
--- a/tests/core/luni-net/Android.mk
+++ b/tests/core/luni-net/Android.mk
@@ -23,14 +23,18 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/tests/api/java/net) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java/) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/luni/AllTestsNet.java \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/libcore/java/net) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/http) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/tests/api/java/net) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java/) \
+	../../../../libcore/luni/src/test/java/tests/luni/AllTestsNet.java
 
 LOCAL_PACKAGE_NAME := android.core.tests.luni.net
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/luni-util/Android.mk b/tests/core/luni-util/Android.mk
index 101cde8..5468c17 100644
--- a/tests/core/luni-util/Android.mk
+++ b/tests/core/luni-util/Android.mk
@@ -23,12 +23,14 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/util) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/tests/api/java/util) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java/) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/luni/AllTestsUtil.java \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := $(call all-java-files-under,../../../../libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/util) \
+	$(call all-java-files-under,../../../../libcore/luni/src/test/java/tests/api/java/util) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java/) \
+	../../../../libcore/luni/src/test/java/tests/luni/AllTestsUtil.java
 
 LOCAL_PACKAGE_NAME := android.core.tests.luni.util
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/math/Android.mk b/tests/core/math/Android.mk
deleted file mode 100644
index 4c559cd..0000000
--- a/tests/core/math/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Math Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/math/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.math
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/math/AndroidManifest.xml b/tests/core/math/AndroidManifest.xml
deleted file mode 100644
index f87fa13..0000000
--- a/tests/core/math/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.math">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/nio/Android.mk b/tests/core/nio/Android.mk
deleted file mode 100644
index 6ebd1bc..0000000
--- a/tests/core/nio/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Nio Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/nio/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.nio
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/nio/AndroidManifest.xml b/tests/core/nio/AndroidManifest.xml
deleted file mode 100644
index 4c79bfa..0000000
--- a/tests/core/nio/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.nio">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/nio_char/Android.mk b/tests/core/nio_char/Android.mk
deleted file mode 100644
index e3b463a..0000000
--- a/tests/core/nio_char/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# NioChar Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/nio_char/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.nio_char
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/nio_char/AndroidManifest.xml b/tests/core/nio_char/AndroidManifest.xml
deleted file mode 100644
index b8de2c9..0000000
--- a/tests/core/nio_char/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.nio_char">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/prefs/Android.mk b/tests/core/prefs/Android.mk
deleted file mode 100644
index f8f225c..0000000
--- a/tests/core/prefs/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Prefs Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/prefs/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.prefs
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/prefs/AndroidManifest.xml b/tests/core/prefs/AndroidManifest.xml
deleted file mode 100644
index d994c72..0000000
--- a/tests/core/prefs/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.prefs">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/regex/Android.mk b/tests/core/regex/Android.mk
deleted file mode 100644
index 70927a0..0000000
--- a/tests/core/regex/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Regex Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/regex/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.regex
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/regex/AndroidManifest.xml b/tests/core/regex/AndroidManifest.xml
deleted file mode 100644
index ddd2165..0000000
--- a/tests/core/regex/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.regex">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/security/Android.mk b/tests/core/security/Android.mk
deleted file mode 100644
index 76c0ca5..0000000
--- a/tests/core/security/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Security Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/security/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.security
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/security/AndroidManifest.xml b/tests/core/security/AndroidManifest.xml
deleted file mode 100644
index 3960a82..0000000
--- a/tests/core/security/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.security">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/sql/Android.mk b/tests/core/sql/Android.mk
deleted file mode 100644
index fe9b4cc..0000000
--- a/tests/core/sql/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Sql Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/sql/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.sql
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/sql/AndroidManifest.xml b/tests/core/sql/AndroidManifest.xml
deleted file mode 100644
index 0ebcab6..0000000
--- a/tests/core/sql/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.sql">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/text/Android.mk b/tests/core/text/Android.mk
deleted file mode 100644
index 8b9fd1f..0000000
--- a/tests/core/text/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Text Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/text/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.text
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/text/AndroidManifest.xml b/tests/core/text/AndroidManifest.xml
deleted file mode 100644
index baf0031..0000000
--- a/tests/core/text/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.text">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/core/xml/Android.mk b/tests/core/xml/Android.mk
index ba784b9..825d14e 100644
--- a/tests/core/xml/Android.mk
+++ b/tests/core/xml/Android.mk
@@ -23,12 +23,14 @@
 ##########################################################
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/xml/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/dom/src/test) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
+LOCAL_SRC_FILES := $(call all-java-files-under,../../../../libcore/xml/src/test/java) \
+	$(call all-java-files-under,../../../../libcore/dom/src/test) \
+	$(call all-java-files-under,../../../../libcore/junit/src/test/java/junit) \
+	$(call all-java-files-under,../../../../libcore/support/src/test/java)
 
 LOCAL_PACKAGE_NAME := android.core.tests.xml
 
+# for java.* javax.* support classes in libcore/support/src/test/java
+LOCAL_DX_FLAGS := --core-library
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/xnet/Android.mk b/tests/core/xnet/Android.mk
deleted file mode 100644
index 2415f38..0000000
--- a/tests/core/xnet/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BUILD_CTSCORE_PACKAGE),)
-    $(error BUILD_CTSCORE_PACKAGE must be defined)
-endif
-
-#
-# Xnet Tests
-##########################################################
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,../../../../dalvik/libcore/x-net/src/test/java) \
-	$(call all-java-files-under,../../../../dalvik/libcore/luni/src/test/java/junit) \
-	$(call all-java-files-under,../../../../dalvik/libcore/support/src/test/java) \
-	../../../../dalvik/libcore/luni/src/test/java/tests/TestSuiteFactory.java
-
-LOCAL_PACKAGE_NAME := android.core.tests.xnet
-
-include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/xnet/AndroidManifest.xml b/tests/core/xnet/AndroidManifest.xml
deleted file mode 100644
index 82e5dd7..0000000
--- a/tests/core/xnet/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.core.tests.xnet">
-    <uses-permission android:name="android.permission.INTERNET" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
-
-</manifest>
diff --git a/tests/res/values-large/configVarying.xml b/tests/res/values-large/configVarying.xml
new file mode 100755
index 0000000..7b2df7c
--- /dev/null
+++ b/tests/res/values-large/configVarying.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple large</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag large</item>
+    </bag>
+    <item type="configVarying" name="large">large</item>
+</resources>
diff --git a/tests/res/values-normal/configVarying.xml b/tests/res/values-normal/configVarying.xml
new file mode 100755
index 0000000..b45ee49
--- /dev/null
+++ b/tests/res/values-normal/configVarying.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple normal</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag normal</item>
+    </bag>
+    <item type="configVarying" name="normal">normal</item>
+</resources>
diff --git a/tests/res/values-small/configVarying.xml b/tests/res/values-small/configVarying.xml
new file mode 100755
index 0000000..15a9f8f
--- /dev/null
+++ b/tests/res/values-small/configVarying.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple small</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag small</item>
+    </bag>
+    <item type="configVarying" name="small">small</item>
+</resources>
diff --git a/tests/res/values-xlarge/configVarying.xml b/tests/res/values-xlarge/configVarying.xml
new file mode 100755
index 0000000..fb9cad7
--- /dev/null
+++ b/tests/res/values-xlarge/configVarying.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple xlarge</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag xlarge</item>
+    </bag>
+    <item type="configVarying" name="xlarge">xlarge</item>
+</resources>
diff --git a/tests/res/values/configVarying.xml b/tests/res/values/configVarying.xml
index a2d5b97..de1b09e 100755
--- a/tests/res/values/configVarying.xml
+++ b/tests/res/values/configVarying.xml
@@ -19,4 +19,8 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag default</item>
     </bag>
+    <item type="configVarying" name="small">default</item>
+    <item type="configVarying" name="normal">default</item>
+    <item type="configVarying" name="large">default</item>
+    <item type="configVarying" name="xlarge">default</item>
 </resources>
diff --git a/tests/src/android/hardware/cts/CameraStubActivity.java b/tests/src/android/hardware/cts/CameraStubActivity.java
index 50bd13b..8ab7fbd 100644
--- a/tests/src/android/hardware/cts/CameraStubActivity.java
+++ b/tests/src/android/hardware/cts/CameraStubActivity.java
@@ -24,9 +24,7 @@
 import com.android.cts.stub.R;
 
 public class CameraStubActivity extends Activity {
-
-    public static SurfaceView mSurfaceView;
-
+    private SurfaceView mSurfaceView;
     private final int LAYOUT_WIDTH = 480;
     private final int LAYOUT_HEIGHT = 320;
 
@@ -43,4 +41,8 @@
         mSurfaceView.getHolder().setFixedSize(LAYOUT_WIDTH, LAYOUT_HEIGHT);
         mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
     }
+
+    public SurfaceView getSurfaceView() {
+        return mSurfaceView;
+    }
 }
diff --git a/tests/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
index 5ce33a0..1861ae2 100644
--- a/tests/tests/app/src/android/app/cts/InstrumentationTest.java
+++ b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -36,10 +36,12 @@
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.test.InstrumentationTestCase;
+import android.view.InputQueue;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.Window;
 import android.view.ViewGroup.LayoutParams;
@@ -956,6 +958,14 @@
             @Override
             public void togglePanel(int featureId, KeyEvent event) {
             }
+            
+            @Override
+            public void takeSurface(SurfaceHolder.Callback2 callback) {
+            }
+            
+            @Override
+            public void takeInputQueue(InputQueue.Callback queue) {
+            }
         }
     }
 
diff --git a/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
new file mode 100644
index 0000000..674fec2
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * Test {@link SharedPreferences}.
+ */
+@TestTargetClass(SharedPreferences.class)
+public class SharedPreferencesTest extends AndroidTestCase {
+    private static final String TAG = "SharedPreferencesTest";
+
+    private Context mContext;
+    private ContextWrapper mContextWrapper;
+
+    private File mPrefsFile;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getContext();
+        mContextWrapper = new ContextWrapper(mContext);
+
+        SharedPreferences prefs = getPrefs();
+        prefs.edit().clear().commit();
+
+        // Duplicated from ContextImpl.java.  Not ideal, but there wasn't a better
+        // way to reach into Context{Wrapper,Impl} to ask where this file lives.
+        mPrefsFile = new File("/data/data/com.android.cts.stub/shared_prefs",
+                              "com.android.cts.stub_preferences.xml");
+        mPrefsFile.delete();
+    }
+
+    private SharedPreferences getPrefs() {
+        return PreferenceManager.getDefaultSharedPreferences(mContext);
+    }
+
+    public void testNoFileInitially() {
+        assertFalse(mPrefsFile.exists());
+    }
+
+    public void testCommitCreatesFiles() {
+        SharedPreferences prefs = getPrefs();
+        assertFalse(mPrefsFile.exists());
+        prefs.edit().putString("foo", "bar").commit();
+        assertTrue(mPrefsFile.exists());
+    }
+
+    public void testDefaults() {
+        SharedPreferences prefs = getPrefs();
+        String key = "not-set";
+        assertFalse(prefs.contains(key));
+        assertEquals(0, prefs.getAll().size());
+        assertTrue(prefs.getAll().isEmpty());
+        assertEquals(false, prefs.getBoolean(key, false));
+        assertEquals(true, prefs.getBoolean(key, true));
+        assertEquals(0.5f, prefs.getFloat(key, 0.5f));
+        assertEquals(123, prefs.getInt(key, 123));
+        assertEquals(999L, prefs.getLong(key, 999L));
+        assertEquals("default", prefs.getString(key, "default"));
+    }
+
+    private abstract class RedundantWriteTest {
+        // Do some initial operation on editor.  No commit needed.
+        public abstract void setUp(SharedPreferences.Editor editor);
+
+        // Do some later operation on editor (e.g. a redundant edit).
+        // No commit needed.
+        public abstract void subsequentEdit(SharedPreferences.Editor editor);
+
+        public boolean expectingMutation() {
+            return false;
+        }
+
+        // Tests that a redundant edit after an initital setup doesn't
+        // result in a duplicate write-out to disk.
+        public final void test() throws Exception {
+            SharedPreferences prefs = getPrefs();
+            SharedPreferences.Editor editor;
+
+            assertFalse(mPrefsFile.exists());
+            prefs.edit().commit();
+            assertTrue(mPrefsFile.exists());
+
+            editor = prefs.edit();
+            setUp(editor);
+            editor.commit();
+            long modtimeMillis1 = mPrefsFile.lastModified();
+
+            // Wait a second and modify the preferences in a dummy,
+            // redundant way.  Wish I could inject a clock or disk mock
+            // here, but can't.  Instead relying on checking modtime of
+            // file on disk.
+            Thread.sleep(1000); // ms
+
+            editor = prefs.edit();
+            subsequentEdit(editor);
+            editor.commit();
+
+            long modtimeMillis2 = mPrefsFile.lastModified();
+            assertEquals(expectingMutation(), modtimeMillis1 != modtimeMillis2);
+        }
+    };
+
+    public void testRedundantBoolean() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.putBoolean("foo", true);
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.putBoolean("foo", true);
+            }
+        }.test();
+    }
+
+    public void testRedundantString() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.putString("foo", "bar");
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.putString("foo", "bar");
+            }
+        }.test();
+    }
+
+    public void testNonRedundantString() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.putString("foo", "bar");
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.putString("foo", "baz");
+            }
+            public boolean expectingMutation() {
+                return true;
+            }
+        }.test();
+    }
+
+    public void testRedundantClear() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.clear();
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.clear();
+            }
+        }.test();
+    }
+
+    public void testNonRedundantClear() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.putString("foo", "bar");
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.clear();
+            }
+            public boolean expectingMutation() {
+                return true;
+            }
+        }.test();
+    }
+
+    public void testRedundantRemove() throws Exception {
+        new RedundantWriteTest() {
+            public void setUp(SharedPreferences.Editor editor) {
+                editor.putString("foo", "bar");
+            }
+            public void subsequentEdit(SharedPreferences.Editor editor) {
+                editor.remove("not-exist-key");
+            }
+        }.test();
+    }
+
+    public void testRedundantCommitWritesFileIfNotAlreadyExisting() {
+        SharedPreferences prefs = getPrefs();
+        assertFalse(mPrefsFile.exists());
+        prefs.edit().putString("foo", "bar").commit();
+        assertTrue(mPrefsFile.exists());
+
+        // Delete the file out from under it.  (not sure why this
+        // would happen in practice, but perhaps the app did it for
+        // some reason...)
+        mPrefsFile.delete();
+
+        // And verify that a redundant edit (which would otherwise not
+        // write do disk), still does write to disk if the file isn't
+        // there.
+        prefs.edit().putString("foo", "bar").commit();
+        assertTrue(mPrefsFile.exists());
+    }
+
+    public void testTorture() {
+        Map<String, String> expectedMap = new HashMap<String, String>();
+        Random rand = new Random();
+
+        SharedPreferences prefs = mContext.getSharedPreferences("torture", Context.MODE_PRIVATE);
+        prefs.edit().clear().commit();
+
+        for (int i = 0; i < 100; i++) {
+            prefs = mContext.getSharedPreferences("torture", Context.MODE_PRIVATE);
+            assertEquals(expectedMap, prefs.getAll());
+
+            String key = new Integer(rand.nextInt(25)).toString();
+            String value = new Integer(i).toString();
+            SharedPreferences.Editor editor = prefs.edit();
+
+            if (rand.nextInt(100) < 85) {
+                Log.d(TAG, "Setting " + key + "=" + value);
+                editor.putString(key, value);
+                expectedMap.put(key, value);
+            } else {
+                Log.d(TAG, "Removing " + key);
+                editor.remove(key);
+                expectedMap.remove(key);
+            }
+
+            // Use apply on most, but commit some too.
+            if (rand.nextInt(100) < 85) {
+                Log.d(TAG, "apply.");
+                editor.apply();
+            } else {
+                Log.d(TAG, "commit.");
+                editor.commit();
+            }
+
+            assertEquals(expectedMap, prefs.getAll());
+        }
+    }
+}
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigTest.java b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
index 276cb35..d68fd19 100755
--- a/tests/tests/content/src/android/content/res/cts/ConfigTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
@@ -43,7 +43,8 @@
         ORIENTATION,
         WIDTH,
         HEIGHT,
-        DENSITY
+        DENSITY,
+        SCREENLAYOUT
     }
 
     private static void checkValue(final Resources res, final int resId,
@@ -129,9 +130,11 @@
                     break;
                 case DENSITY:
                     // this is the ratio from the standard
-
                     mMetrics.density = (((float)value)/((float)DisplayMetrics.DENSITY_DEFAULT));
                     break;
+                case SCREENLAYOUT:
+                    mConfig.screenLayout = value;
+                    break;
                 default:
                     assert(false);
                     break;
@@ -303,6 +306,34 @@
         checkValue(res, R.configVarying.simple, "simple square");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag square"});
+
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_SMALL);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple small");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag small"});
+
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_NORMAL);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple normal");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag normal"});
+
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_LARGE);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple large");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag large"});
+
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_XLARGE);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple xlarge");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag xlarge"});
     }
     
     @MediumTest
@@ -378,6 +409,47 @@
                 R.styleable.TestConfig, new String[]{"bag 240dpi"});
     }
 
+    @MediumTest
+    public void testScreenSize() throws Exception {
+        // ensure that we fall back to the best available screen size
+        // for a given configuration.
+        TotalConfig config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_SMALL);
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple small");
+        checkValue(res, R.configVarying.small, "small");
+        checkValue(res, R.configVarying.normal, "default");
+        checkValue(res, R.configVarying.large, "default");
+        checkValue(res, R.configVarying.xlarge, "default");
+        
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_NORMAL);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple normal");
+        checkValue(res, R.configVarying.small, "default");
+        checkValue(res, R.configVarying.normal, "normal");
+        checkValue(res, R.configVarying.large, "default");
+        checkValue(res, R.configVarying.xlarge, "default");
+        
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_LARGE);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple large");
+        checkValue(res, R.configVarying.small, "default");
+        checkValue(res, R.configVarying.normal, "normal");
+        checkValue(res, R.configVarying.large, "large");
+        checkValue(res, R.configVarying.xlarge, "default");
+        
+        config = new TotalConfig();
+        config.setProperty(Properties.SCREENLAYOUT, Configuration.SCREENLAYOUT_SIZE_XLARGE);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple xlarge");
+        checkValue(res, R.configVarying.small, "default");
+        checkValue(res, R.configVarying.normal, "normal");
+        checkValue(res, R.configVarying.large, "large");
+        checkValue(res, R.configVarying.xlarge, "xlarge");
+    }
+
 // TODO - add tests for special cases - ie, other key params seem ignored if 
 // nokeys is set
 
@@ -421,7 +493,8 @@
          */
 
         /**
-         * Precidence order: mcc, mnc, locale, orientation, density,
+         * Precidence order: mcc, mnc, locale, screenlayout-size,
+         * screenlayout-long, orientation, density,
          * touchscreen, hidden, keyboard, navigation, width-height
          */
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index d69dd4f..041de94 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -34,7 +34,6 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.Suppress;
 
 @TestTargetClass(NinePatch.class)
 public class NinePatchTest extends AndroidTestCase {
@@ -174,7 +173,6 @@
         method = "hasAlpha",
         args = {}
     )
-    @Suppress // Suppressed for current release
     public void testHasAlpha() {
         assertFalse(mNinePatch.hasAlpha());
         assertEquals(mNinePatch.hasAlpha(), mBitmap.hasAlpha());
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
index 864a1ab..21e9796 100644
--- a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
@@ -25,10 +25,10 @@
 import android.graphics.BitmapFactory;
 import android.graphics.ImageFormat;
 import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.ErrorCallback;
 import android.hardware.Camera.Parameters;
 import android.hardware.Camera.PictureCallback;
-import android.hardware.Camera.PreviewCallback;
 import android.hardware.Camera.ShutterCallback;
 import android.hardware.Camera.Size;
 import android.media.ExifInterface;
@@ -61,7 +61,7 @@
             "/test.jpg";
     private byte[] mJpegData;
 
-    private boolean mRawPreviewCallbackResult = false;
+    private boolean mPreviewCallbackResult = false;
     private boolean mShutterCallbackResult = false;
     private boolean mRawPictureCallbackResult = false;
     private boolean mJpegPictureCallbackResult = false;
@@ -72,7 +72,7 @@
     private static final int WAIT_FOR_FOCUS_TO_COMPLETE = 3000;
     private static final int WAIT_FOR_SNAPSHOT_TO_COMPLETE = 5000;
 
-    private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback();
+    private PreviewCallback mPreviewCallback = new PreviewCallback();
     private TestShutterCallback mShutterCallback = new TestShutterCallback();
     private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
     private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback();
@@ -153,18 +153,13 @@
     }
 
     //Implement the previewCallback
-    private final class RawPreviewCallback implements PreviewCallback {
-        public void onPreviewFrame(byte [] rawData, Camera camera) {
-            if (LOGV) Log.v(TAG, "Preview callback start");
-            int rawDataLength = 0;
-            if (rawData != null) {
-                rawDataLength = rawData.length;
-            }
-            if (rawDataLength > 0) {
-                mRawPreviewCallbackResult = true;
-            } else {
-                mRawPreviewCallbackResult = false;
-            }
+    private final class PreviewCallback
+            implements android.hardware.Camera.PreviewCallback {
+        public void onPreviewFrame(byte [] data, Camera camera) {
+            assertNotNull(data);
+            Size size = camera.getParameters().getPreviewSize();
+            assertEquals(size.width * size.height * 3 / 2, data.length);
+            mPreviewCallbackResult = true;
             mCamera.stopPreview();
             if (LOGV) Log.v(TAG, "notify the preview callback");
             mPreviewDone.open();
@@ -265,10 +260,7 @@
     }
 
     private void checkPreviewCallback() throws Exception {
-        SurfaceHolder mSurfaceHolder;
-
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         if (LOGV) Log.v(TAG, "check preview callback");
         mCamera.startPreview();
         waitForPreviewDone();
@@ -317,9 +309,7 @@
     public void testTakePicture() throws Exception {
         initializeMessageLooper();
         Size pictureSize = mCamera.getParameters().getPictureSize();
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         mCamera.startPreview();
         mCamera.autoFocus(mAutoFocusCallback);
         assertTrue(waitForFocusDone());
@@ -329,16 +319,12 @@
         terminateMessageLooper();
         assertTrue(mShutterCallbackResult);
         assertTrue(mJpegPictureCallbackResult);
-        assertTrue(mJpegData != null);
+        assertNotNull(mJpegData);
         Bitmap b = BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length);
-        assertEquals(b.getWidth(), pictureSize.width);
-        assertEquals(b.getHeight(), pictureSize.height);
+        assertEquals(pictureSize.width, b.getWidth());
+        assertEquals(pictureSize.height, b.getHeight());
     }
 
-    /*
-     * Test case 2: Set the preview and
-     * verify the RawPreviewCallback is called
-     */
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
@@ -377,13 +363,35 @@
         )
     })
     @UiThreadTest
-    public void testCheckPreview() throws Exception {
+    public void testPreviewCallback() throws Exception {
         initializeMessageLooper();
-        mCamera.setPreviewCallback(mRawPreviewCallback);
+        mCamera.setPreviewCallback(mPreviewCallback);
         mCamera.setErrorCallback(mErrorCallback);
         checkPreviewCallback();
         terminateMessageLooper();
-        assertTrue(mRawPreviewCallbackResult);
+        assertTrue(mPreviewCallbackResult);
+
+        mPreviewCallbackResult = false;
+        initializeMessageLooper();
+        checkPreviewCallback();
+        terminateMessageLooper();
+        assertFalse(mPreviewCallbackResult);
+
+        // Test all preview sizes.
+        initializeMessageLooper();
+        Parameters parameters = mCamera.getParameters();
+        for (Size size: parameters.getSupportedPreviewSizes()) {
+            mPreviewCallbackResult = false;
+            mCamera.setPreviewCallback(mPreviewCallback);
+            parameters.setPreviewSize(size.width, size.height);
+            mCamera.setParameters(parameters);
+            assertEquals(size, mCamera.getParameters().getPreviewSize());
+            mCamera.startPreview();
+            waitForPreviewDone();
+            assertTrue(mPreviewCallbackResult);
+            mCamera.stopPreview();
+        }
+        terminateMessageLooper();
     }
 
     @TestTargetNew(
@@ -394,16 +402,16 @@
     @UiThreadTest
     public void testSetOneShotPreviewCallback() throws Exception {
         initializeMessageLooper();
-        mCamera.setOneShotPreviewCallback(mRawPreviewCallback);
+        mCamera.setOneShotPreviewCallback(mPreviewCallback);
         checkPreviewCallback();
         terminateMessageLooper();
-        assertTrue(mRawPreviewCallbackResult);
+        assertTrue(mPreviewCallbackResult);
 
-        mRawPreviewCallbackResult = false;
+        mPreviewCallbackResult = false;
         initializeMessageLooper();
         checkPreviewCallback();
         terminateMessageLooper();
-        assertFalse(mRawPreviewCallbackResult);
+        assertFalse(mPreviewCallbackResult);
     }
 
     @TestTargetNew(
@@ -413,38 +421,37 @@
     )
     @UiThreadTest
     public void testSetPreviewDisplay() throws Exception {
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
+        SurfaceHolder holder = getActivity().getSurfaceView().getHolder();
         initializeMessageLooper();
 
         // Check the order: startPreview->setPreviewDisplay.
-        mCamera.setOneShotPreviewCallback(mRawPreviewCallback);
+        mCamera.setOneShotPreviewCallback(mPreviewCallback);
         mCamera.startPreview();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(holder);
         waitForPreviewDone();
         terminateMessageLooper();
-        assertTrue(mRawPreviewCallbackResult);
+        assertTrue(mPreviewCallbackResult);
 
         // Check the order: setPreviewDisplay->startPreview.
         initializeMessageLooper();
-        mRawPreviewCallbackResult = false;
-        mCamera.setOneShotPreviewCallback(mRawPreviewCallback);
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mPreviewCallbackResult = false;
+        mCamera.setOneShotPreviewCallback(mPreviewCallback);
+        mCamera.setPreviewDisplay(holder);
         mCamera.startPreview();
         waitForPreviewDone();
         mCamera.stopPreview();
-        assertTrue(mRawPreviewCallbackResult);
+        assertTrue(mPreviewCallbackResult);
 
         // Check the order: setting preview display to null->startPreview->
         // setPreviewDisplay.
-        mRawPreviewCallbackResult = false;
-        mCamera.setOneShotPreviewCallback(mRawPreviewCallback);
+        mPreviewCallbackResult = false;
+        mCamera.setOneShotPreviewCallback(mPreviewCallback);
         mCamera.setPreviewDisplay(null);
         mCamera.startPreview();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(holder);
         waitForPreviewDone();
         terminateMessageLooper();
-        assertTrue(mRawPreviewCallbackResult);
+        assertTrue(mPreviewCallbackResult);
     }
 
     @TestTargetNew(
@@ -471,9 +478,7 @@
         }
 
         // Start preview.
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         mCamera.startPreview();
 
         // Check setting orientation during preview is not allowed.
@@ -531,10 +536,10 @@
         assertTrue(origPreviewFrameRate > 0);
 
         // The default preview format must be yuv420 (NV21).
-        assertTrue(origPreviewFormat == ImageFormat.NV21);
+        assertEquals(ImageFormat.NV21, origPreviewFormat);
 
         // The default picture format must be Jpeg.
-        assertTrue(origPictureFormat == ImageFormat.JPEG);
+        assertEquals(ImageFormat.JPEG, origPictureFormat);
 
         // If camera supports flash, the default flash mode must be off.
         String flashMode = parameters.getFlashMode();
@@ -557,7 +562,7 @@
         assertTrue(pictureFormats != null && pictureFormats.size() != 0);
         assertTrue(frameRates != null && frameRates.size() != 0);
         assertTrue(focusModes != null && focusModes.size() != 0);
-        assertTrue(focusMode != null);
+        assertNotNull(focusMode);
         assertTrue(focalLength > 0);
         assertTrue(horizontalViewAngle > 0 && horizontalViewAngle <= 360);
         assertTrue(verticalViewAngle > 0 && verticalViewAngle <= 360);
@@ -567,34 +572,34 @@
         // If a parameter is supported, both getXXX and getSupportedXXX have to
         // be non null.
         if (parameters.getWhiteBalance() != null) {
-            assertTrue(parameters.getSupportedWhiteBalance() != null);
+            assertNotNull(parameters.getSupportedWhiteBalance());
         }
         if (parameters.getSupportedWhiteBalance() != null) {
-            assertTrue(parameters.getWhiteBalance() != null);
+            assertNotNull(parameters.getWhiteBalance());
         }
         if (parameters.getColorEffect() != null) {
-            assertTrue(parameters.getSupportedColorEffects() != null);
+            assertNotNull(parameters.getSupportedColorEffects());
         }
         if (parameters.getSupportedColorEffects() != null) {
-            assertTrue(parameters.getColorEffect() != null);
+            assertNotNull(parameters.getColorEffect());
         }
         if (parameters.getAntibanding() != null) {
-            assertTrue(parameters.getSupportedAntibanding() != null);
+            assertNotNull(parameters.getSupportedAntibanding());
         }
         if (parameters.getSupportedAntibanding() != null) {
-            assertTrue(parameters.getAntibanding() != null);
+            assertNotNull(parameters.getAntibanding());
         }
         if (parameters.getSceneMode() != null) {
-            assertTrue(parameters.getSupportedSceneModes() != null);
+            assertNotNull(parameters.getSupportedSceneModes());
         }
         if (parameters.getSupportedSceneModes() != null) {
-            assertTrue(parameters.getSceneMode() != null);
+            assertNotNull(parameters.getSceneMode());
         }
         if (parameters.getFlashMode() != null) {
-            assertTrue(parameters.getSupportedFlashModes() != null);
+            assertNotNull(parameters.getSupportedFlashModes());
         }
         if (parameters.getSupportedFlashModes() != null) {
-            assertTrue(parameters.getFlashMode() != null);
+            assertNotNull(parameters.getFlashMode());
         }
 
         // Set the parameters.
@@ -614,20 +619,19 @@
         mCamera.setParameters(parameters);
         Parameters paramActual = mCamera.getParameters();
 
-        // camera may not accept exact parameters, but values must be in valid range
         assertTrue(isValidPixelFormat(paramActual.getPictureFormat()));
-        assertEquals(paramActual.getPictureSize().width, pictureSize.width);
-        assertEquals(paramActual.getPictureSize().height, pictureSize.height);
+        assertEquals(pictureSize.width, paramActual.getPictureSize().width);
+        assertEquals(pictureSize.height, paramActual.getPictureSize().height);
         assertTrue(isValidPixelFormat(paramActual.getPreviewFormat()));
-        assertEquals(paramActual.getPreviewSize().width, previewSize.width);
-        assertEquals(paramActual.getPreviewSize().height, previewSize.height);
+        assertEquals(previewSize.width, paramActual.getPreviewSize().width);
+        assertEquals(previewSize.height, paramActual.getPreviewSize().height);
         assertTrue(paramActual.getPreviewFrameRate() > 0);
 
         checkExposureCompensation(parameters);
     }
 
     private void checkExposureCompensation(Parameters parameters) {
-        assertEquals(parameters.getExposureCompensation(), 0);
+        assertEquals(0, parameters.getExposureCompensation());
         int max = parameters.getMaxExposureCompensation();
         int min = parameters.getMinExposureCompensation();
         float step = parameters.getExposureCompensationStep();
@@ -675,29 +679,30 @@
         assertTrue(sizes.contains(mCamera.new Size(0, 0)));
 
         // Test if the thumbnail size matches the setting.
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         mCamera.startPreview();
         mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
         waitForSnapshotDone();
-        assertEquals(mJpegPictureCallbackResult, true);
+        assertTrue(mJpegPictureCallbackResult);
         ExifInterface exif = new ExifInterface(JPEG_PATH);
         assertTrue(exif.hasThumbnail());
         byte[] thumb = exif.getThumbnail();
         Bitmap b = BitmapFactory.decodeByteArray(thumb, 0, thumb.length);
-        assertEquals(b.getWidth(), size.width);
-        assertEquals(b.getHeight(), size.height);
+        assertEquals(size.width, b.getWidth());
+        assertEquals(size.height, b.getHeight());
 
         // Test no thumbnail case.
         p.setJpegThumbnailSize(0, 0);
         mCamera.setParameters(p);
+        Size actual = mCamera.getParameters().getJpegThumbnailSize();
+        assertEquals(0, actual.width);
+        assertEquals(0, actual.height);
         mCamera.startPreview();
         mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
         waitForSnapshotDone();
-        assertEquals(mJpegPictureCallbackResult, true);
+        assertTrue(mJpegPictureCallbackResult);
         exif = new ExifInterface(JPEG_PATH);
-        assertTrue(!exif.hasThumbnail());
+        assertFalse(exif.hasThumbnail());
 
         terminateMessageLooper();
     }
@@ -706,26 +711,18 @@
     public void testJpegExif() throws Exception {
         initializeMessageLooper();
         Camera.Parameters parameters = mCamera.getParameters();
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         mCamera.startPreview();
         double focalLength = (double)parameters.getFocalLength();
         mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
         waitForSnapshotDone();
         ExifInterface exif = new ExifInterface(JPEG_PATH);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_MAKE) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_MODEL) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_DATETIME) != null);
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_MAKE));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_MODEL));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_DATETIME));
         assertTrue(exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0) != 0);
         assertTrue(exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0) != 0);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP), null);
-        assertEquals(exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD), null);
+        checkGpsDataNull(exif);
         double exifFocalLength = (double)exif.getAttributeDouble(
                 ExifInterface.TAG_FOCAL_LENGTH, -1);
         assertEquals(focalLength, exifFocalLength, 0.001);
@@ -742,17 +739,36 @@
         mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
         waitForSnapshotDone();
         exif = new ExifInterface(JPEG_PATH);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP) != null);
-        assertTrue(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP) != null);
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
+        assertNotNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
         assertEquals(thirtyTwoCharacters,
                 exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD));
+
+        // Test gps tags do not exist after calling removeGpsData.
+        mCamera.startPreview();
+        parameters.removeGpsData();
+        mCamera.setParameters(parameters);
+        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
+        waitForSnapshotDone();
+        exif = new ExifInterface(JPEG_PATH);
+        checkGpsDataNull(exif);
         terminateMessageLooper();
     }
 
+    private void checkGpsDataNull(ExifInterface exif) {
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP));
+        assertNull(exif.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD));
+    }
+
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
@@ -770,7 +786,7 @@
         initializeMessageLooper();
         Camera.Parameters parameters = mCamera.getParameters();
         SurfaceHolder surfaceHolder;
-        surfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
+        surfaceHolder = getActivity().getSurfaceView().getHolder();
         Size size = parameters.getPreviewSize();
         mCamera.setParameters(parameters);
         mCamera.setPreviewDisplay(surfaceHolder);
@@ -836,39 +852,50 @@
     public void testPreviewCallbackWithBuffer() throws Exception {
         initializeMessageLooper();
         SurfaceHolder surfaceHolder;
-        surfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
+        surfaceHolder = getActivity().getSurfaceView().getHolder();
         mCamera.setPreviewDisplay(surfaceHolder);
-        Size size = mCamera.getParameters().getPreviewSize();
+        Parameters parameters = mCamera.getParameters();
         PreviewCallbackWithBuffer callback = new PreviewCallbackWithBuffer();
-        callback.mBuffer1 = new byte[size.width * size.height * 3 / 2 + 1];
-        callback.mBuffer2 = new byte[size.width * size.height * 3 / 2 + 1];
-        callback.mBuffer3 = new byte[size.width * size.height * 3 / 2 + 1];
+        // Test all preview sizes.
+        for (Size size: parameters.getSupportedPreviewSizes()) {
+            parameters.setPreviewSize(size.width, size.height);
+            mCamera.setParameters(parameters);
+            assertEquals(size, mCamera.getParameters().getPreviewSize());
+            callback.mNumCbWithBuffer1 = 0;
+            callback.mNumCbWithBuffer2 = 0;
+            callback.mNumCbWithBuffer3 = 0;
+            callback.mBuffer1 = new byte[size.width * size.height * 3 / 2];
+            callback.mBuffer2 = new byte[size.width * size.height * 3 / 2];
+            callback.mBuffer3 = new byte[size.width * size.height * 3 / 2];
 
-        // Test if we can get the preview callbacks with specified buffers.
-        mCamera.addCallbackBuffer(callback.mBuffer1);
-        mCamera.addCallbackBuffer(callback.mBuffer2);
-        mCamera.setPreviewCallbackWithBuffer(callback);
-        mCamera.startPreview();
-        waitForPreviewDone();
-        assertEquals(1, callback.mNumCbWithBuffer1);
-        assertEquals(1, callback.mNumCbWithBuffer2);
-        assertEquals(0, callback.mNumCbWithBuffer3);
+            // Test if we can get the preview callbacks with specified buffers.
+            mCamera.addCallbackBuffer(callback.mBuffer1);
+            mCamera.addCallbackBuffer(callback.mBuffer2);
+            mCamera.setPreviewCallbackWithBuffer(callback);
+            mCamera.startPreview();
+            waitForPreviewDone();
+            assertEquals(1, callback.mNumCbWithBuffer1);
+            assertEquals(1, callback.mNumCbWithBuffer2);
+            assertEquals(0, callback.mNumCbWithBuffer3);
 
-        // Test if preview callback with buffer still works during preview.
-        callback.mNumCbWithBuffer1 = callback.mNumCbWithBuffer2 = 0;
-        mCamera.addCallbackBuffer(callback.mBuffer3);
-        waitForPreviewDone();
-        assertEquals(0, callback.mNumCbWithBuffer1);
-        assertEquals(0, callback.mNumCbWithBuffer2);
-        assertEquals(1, callback.mNumCbWithBuffer3);
+            // Test if preview callback with buffer still works during preview.
+            mCamera.addCallbackBuffer(callback.mBuffer3);
+            waitForPreviewDone();
+            assertEquals(1, callback.mNumCbWithBuffer1);
+            assertEquals(1, callback.mNumCbWithBuffer2);
+            assertEquals(1, callback.mNumCbWithBuffer3);
+            mCamera.setPreviewCallbackWithBuffer(null);
+            mCamera.stopPreview();
+        }
         terminateMessageLooper();
     }
 
-    private final class PreviewCallbackWithBuffer implements PreviewCallback {
+    private final class PreviewCallbackWithBuffer
+            implements android.hardware.Camera.PreviewCallback {
         public int mNumCbWithBuffer1, mNumCbWithBuffer2, mNumCbWithBuffer3;
         public byte[] mBuffer1, mBuffer2, mBuffer3;
         public void onPreviewFrame(byte[] data, Camera camera) {
-            assert(data != null);
+            assertNotNull(data);
             if (data == mBuffer1) {
                 mNumCbWithBuffer1++;
             } else if (data == mBuffer2) {
@@ -915,45 +942,49 @@
         Parameters parameters = mCamera.getParameters();
         if (!parameters.isZoomSupported()) return;
 
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
+
         // Test the zoom parameters.
-        assertEquals(parameters.getZoom(), 0);  // default zoom should be 0.
-        int maxZoom = parameters.getMaxZoom();
-        assertTrue(maxZoom >= 0);
-        if (maxZoom > 0) {
+        assertEquals(0, parameters.getZoom());  // default zoom should be 0.
+        for (Size size: parameters.getSupportedPreviewSizes()) {
+            parameters = mCamera.getParameters();
+            parameters.setPreviewSize(size.width, size.height);
+            mCamera.setParameters(parameters);
+            parameters = mCamera.getParameters();
+            int maxZoom = parameters.getMaxZoom();
+            assertTrue(maxZoom >= 0);
+
             // Zoom ratios should be sorted from small to large.
             List<Integer> ratios = parameters.getZoomRatios();
-            assertEquals(ratios.size(), maxZoom + 1);
-            assertEquals(ratios.get(0).intValue(), 100);
+            assertEquals(maxZoom + 1, ratios.size());
+            assertEquals(100, ratios.get(0).intValue());
             for (int i = 0; i < ratios.size() - 1; i++) {
                 assertTrue(ratios.get(i) < ratios.get(i + 1));
             }
-        }
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
-        mCamera.startPreview();
-        waitForPreviewDone();
+            mCamera.startPreview();
+            waitForPreviewDone();
 
-        // Test each zoom step.
-        for (int i = 0; i <= maxZoom; i++) {
-            parameters.setZoom(i);
-            mCamera.setParameters(parameters);
-            assertEquals(i, parameters.getZoom());
-        }
+            // Test each zoom step.
+            for (int i = 0; i <= maxZoom; i++) {
+                parameters.setZoom(i);
+                mCamera.setParameters(parameters);
+                assertEquals(i, mCamera.getParameters().getZoom());
+            }
 
-        // It should throw exception if an invalid value is passed.
-        try {
-            parameters.setZoom(maxZoom + 1);
-            mCamera.setParameters(parameters);
-            fail("setZoom should throw exception.");
-        } catch (RuntimeException e) {
-            // expected
-        }
-        parameters = mCamera.getParameters();
-        assertEquals(maxZoom, parameters.getZoom());
+            // It should throw exception if an invalid value is passed.
+            try {
+                parameters.setZoom(maxZoom + 1);
+                mCamera.setParameters(parameters);
+                fail("setZoom should throw exception.");
+            } catch (RuntimeException e) {
+                // expected
+            }
+            assertEquals(maxZoom, mCamera.getParameters().getZoom());
 
-        mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
-        waitForSnapshotDone();
+            mCamera.takePicture(mShutterCallback, mRawPictureCallback,
+                                mJpegPictureCallback);
+            waitForSnapshotDone();
+        }
     }
 
     private void testSmoothZoom() throws Exception {
@@ -961,10 +992,8 @@
         if (!parameters.isSmoothZoomSupported()) return;
         assertTrue(parameters.isZoomSupported());
 
-        SurfaceHolder mSurfaceHolder;
-        mSurfaceHolder = CameraStubActivity.mSurfaceView.getHolder();
         ZoomListener zoomListener = new ZoomListener();
-        mCamera.setPreviewDisplay(mSurfaceHolder);
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
         mCamera.setZoomChangeListener(zoomListener);
         mCamera.startPreview();
         waitForPreviewDone();
@@ -973,8 +1002,10 @@
         int maxZoom = parameters.getMaxZoom();
         parameters.setZoom(maxZoom);
         mCamera.setParameters(parameters);
+        assertEquals(maxZoom, mCamera.getParameters().getZoom());
         parameters.setZoom(0);
         mCamera.setParameters(parameters);
+        assertEquals(0, mCamera.getParameters().getZoom());
         assertFalse(zoomListener.mZoomDone.block(500));
 
         // Nothing will happen if zoom is not moving.
@@ -1000,7 +1031,7 @@
             Log.e(TAG, "zoomListener.mStopped = " + zoomListener.mStopped);
             zoomListener.mZoomDone.close();
             mCamera.startSmoothZoom(maxZoom / 2);
-            assertEquals(true, zoomListener.mZoomDone.block(5000));
+            assertTrue(zoomListener.mZoomDone.block(5000));
             assertEquals(maxZoom - (maxZoom / 2), zoomListener.mValues.size());
             int i = maxZoom - 1;
             for(Integer value: zoomListener.mValues) {
@@ -1023,6 +1054,7 @@
         zoomListener.mZoomDone.close();
         parameters.setZoom(0);
         mCamera.setParameters(parameters);
+        assertEquals(0, mCamera.getParameters().getZoom());
         mCamera.startSmoothZoom(maxZoom);
         mCamera.stopSmoothZoom();
         assertTrue(zoomListener.mZoomDone.block(5000));
@@ -1041,11 +1073,209 @@
         public void onZoomChange(int value, boolean stopped, Camera camera) {
             mValues.add(value);
             assertEquals(value, camera.getParameters().getZoom());
-            assertEquals(false, mStopped);
+            assertFalse(mStopped);
             mStopped = stopped;
             if (stopped) {
                 mZoomDone.open();
             }
         }
     }
+
+    @UiThreadTest
+    public void testFocusDistances() throws Exception {
+        initializeMessageLooper();
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
+        mCamera.startPreview();
+        waitForPreviewDone();
+        Parameters parameters = mCamera.getParameters();
+
+        // Test every supported focus mode.
+        for (String focusMode: parameters.getSupportedFocusModes()) {
+            parameters.setFocusMode(focusMode);
+            mCamera.setParameters(parameters);
+            parameters = mCamera.getParameters();
+            assertEquals(focusMode, parameters.getFocusMode());
+            checkFocusDistances(parameters);
+            if (Parameters.FOCUS_MODE_AUTO.equals(focusMode)
+                    || Parameters.FOCUS_MODE_MACRO.equals(focusMode)) {
+                mCamera.autoFocus(mAutoFocusCallback);
+                assertTrue(waitForFocusDone());
+                parameters = mCamera.getParameters();
+                checkFocusDistances(parameters);
+            }
+        }
+
+        // Test if the method throws exception if the argument is invalid.
+        try {
+            parameters.getFocusDistances(null);
+            fail("getFocusDistances should not accept null.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            parameters.getFocusDistances(new float[2]);
+            fail("getFocusDistances should not accept a float array with two elements.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            parameters.getFocusDistances(new float[4]);
+            fail("getFocusDistances should not accept a float array with four elements.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        terminateMessageLooper();
+    }
+
+    private void checkFocusDistances(Parameters parameters) {
+        float[] distances = new float[3];
+        parameters.getFocusDistances(distances);
+
+        // Focus distances should be greater than 0.
+        assertTrue(distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX] > 0);
+        assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] > 0);
+        assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] > 0);
+
+        // Make sure far focus distance >= optimal focus distance >= near focus distance.
+        assertTrue(distances[Parameters.FOCUS_DISTANCE_FAR_INDEX] >=
+                   distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);
+        assertTrue(distances[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX] >=
+                   distances[Parameters.FOCUS_DISTANCE_NEAR_INDEX]);
+
+        // Far focus distance should be infinity in infinity focus mode.
+        if (Parameters.FOCUS_MODE_INFINITY.equals(parameters.getFocusMode())) {
+            assertEquals(Float.POSITIVE_INFINITY,
+                         distances[Parameters.FOCUS_DISTANCE_FAR_INDEX]);
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "cancelAutofocus",
+            args = {}
+        )
+    })
+    @UiThreadTest
+    public void testCancelAutofocus() throws Exception {
+        initializeMessageLooper();
+        mCamera.setPreviewDisplay(getActivity().getSurfaceView().getHolder());
+        mCamera.startPreview();
+
+        // No op if autofocus is not in progress.
+        mCamera.cancelAutoFocus();
+
+        // Try to cancel autofocus immediately.
+        mCamera.autoFocus(mAutoFocusCallback);
+        mCamera.cancelAutoFocus();
+        checkFocusDistanceNotChanging();
+
+        // Try to cancel autofocus after it starts for some time.
+        mCamera.autoFocus(mAutoFocusCallback);
+        Thread.sleep(500);
+        mCamera.cancelAutoFocus();
+        checkFocusDistanceNotChanging();
+
+        // Try to cancel autofocus after it completes. It should be no op.
+        mCamera.autoFocus(mAutoFocusCallback);
+        assertTrue(waitForFocusDone());
+        mCamera.cancelAutoFocus();
+
+        // Test the case calling cancelAutoFocus and release in a row.
+        mCamera.autoFocus(mAutoFocusCallback);
+        mCamera.cancelAutoFocus();
+        mCamera.release();
+
+        // Ensure the camera can be opened if release is called right after AF.
+        mCamera = Camera.open();
+        mCamera.startPreview();
+        mCamera.autoFocus(mAutoFocusCallback);
+        mCamera.release();
+
+        terminateMessageLooper();
+    }
+
+    private void checkFocusDistanceNotChanging() throws Exception {
+        float[] distances1 = new float[3];
+        float[] distances2 = new float[3];
+        Parameters parameters = mCamera.getParameters();
+        parameters.getFocusDistances(distances1);
+        Thread.sleep(100);
+        parameters = mCamera.getParameters();
+        parameters.getFocusDistances(distances2);
+        assertEquals(distances1[Parameters.FOCUS_DISTANCE_NEAR_INDEX],
+                     distances2[Parameters.FOCUS_DISTANCE_NEAR_INDEX]);
+        assertEquals(distances1[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX],
+                     distances2[Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);
+        assertEquals(distances1[Parameters.FOCUS_DISTANCE_FAR_INDEX],
+                     distances2[Parameters.FOCUS_DISTANCE_FAR_INDEX]);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getNumberOfCameras",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCameraInfo",
+            args = {int.class, CameraInfo.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "open",
+            args = {int.class}
+        )
+    })
+    @UiThreadTest
+    public void testMultipleCameras() throws Exception {
+        int nCameras = Camera.getNumberOfCameras();
+        Log.v(TAG, "total " + nCameras + " cameras");
+        assertTrue(nCameras > 0);
+
+        for (int id = -1; id <= nCameras; id++) {
+            Log.v(TAG, "testing camera #" + id);
+
+            boolean isBadId = (id < 0 || id >= nCameras);
+
+            CameraInfo info = new CameraInfo();
+            try {
+                Camera.getCameraInfo(id, info);
+                if (isBadId) {
+                    fail("getCameraInfo should not accept bad cameraId (" + id + ")");
+                }
+            } catch (RuntimeException e) {
+                if (!isBadId) throw e;
+            }
+
+            int facing = info.facing;
+            int orientation = info.orientation;
+            assertTrue(facing == CameraInfo.CAMERA_FACING_BACK ||
+                       facing == CameraInfo.CAMERA_FACING_FRONT);
+            assertTrue(orientation == 0 || orientation == 90 ||
+                       orientation == 180 || orientation == 270);
+
+            Camera camera = null;
+            try {
+                camera = Camera.open(id);
+                if (isBadId) {
+                    fail("open() should not accept bad cameraId (" + id + ")");
+                }
+            } catch (RuntimeException e) {
+                if (!isBadId) throw e;
+            } finally {
+                if (camera != null) {
+                    camera.release();
+                }
+            }
+        }
+    }
+
+    private void assertEquals(Size expected, Size actual) {
+        assertEquals(expected.width, actual.width);
+        assertEquals(expected.height, actual.height);
+    }
 }
diff --git a/tests/tests/jni/libjnitest/helper.h b/tests/tests/jni/libjnitest/helper.h
index 6771d2f..58a3407 100644
--- a/tests/tests/jni/libjnitest/helper.h
+++ b/tests/tests/jni/libjnitest/helper.h
@@ -47,7 +47,7 @@
  * @param ... printf-style arguments
  * @return an allocated (char *) containing the formatted result
  */
-char *failure(const char *format, ...);
+char *failure(const char *format, ...) __attribute__((format(printf, 1, 2)));
 
 /**
  * Runs a list of tests. It will run all the tests, collecting as output
diff --git a/tests/tests/media/src/android/media/cts/AudioEffectTest.java b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
new file mode 100644
index 0000000..3d458c4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import com.android.cts.stub.R;
+
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.PresetReverb;
+import android.media.EnvironmentalReverb;
+import android.media.Equalizer;
+import android.media.MediaPlayer;
+
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import java.util.UUID;
+
+@TestTargetClass(AudioEffect.class)
+public class AudioEffectTest extends AndroidTestCase {
+
+    private String TAG = "AudioEffectTest";
+    private final static int MIN_NUMBER_EFFECTS = 5;
+    // allow +/- 5% tolerance between set and get delays
+    private final static float DELAY_TOLERANCE = 1.05f;
+    // allow +/- 5% tolerance between set and get ratios
+    private final static float RATIO_TOLERANCE = 1.05f;
+
+    private AudioEffect mEffect = null;
+    private AudioEffect mEffect2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private MediaPlayer mMediaPlayer = null;
+    private int mError = 0;
+
+    private final Object mLock = new Object();
+
+
+    //-----------------------------------------------------------------
+    // AUDIOEFFECT TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - static methods
+    //----------------------------------
+
+    //Test case 0.0: test queryEffects() and platfrom at least provides Equalizer, Bass Boost,
+    // Virtualizer, Environmental reverb and Preset reverb effects
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "queryEffects",
+            args = {}
+        )
+    })
+    public void test0_0QueryEffects() throws Exception {
+
+        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
+
+        assertTrue("test0_0QueryEffects: number of effects < MIN_NUMBER_EFFECTS: "+desc.length,
+                (desc.length >= MIN_NUMBER_EFFECTS));
+
+        boolean hasEQ = false;
+        boolean hasBassBoost = false;
+        boolean hasVirtualizer = false;
+        boolean hasEnvReverb = false;
+        boolean hasPresetReverb = false;
+
+        for (int i = 0; i < desc.length; i++) {
+            if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
+                hasEQ = true;
+            } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
+                hasBassBoost = true;
+            } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
+                hasVirtualizer = true;
+            } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
+                hasEnvReverb = true;
+            } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_PRESET_REVERB)) {
+                hasPresetReverb = true;
+            }
+        }
+        assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
+        assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost);
+        assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer);
+        assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb);
+        assertTrue("test0_0QueryEffects: preset reverb not found", hasPresetReverb);
+    }
+
+    //-----------------------------------------------------------------
+    // 1 - constructor
+    //----------------------------------
+
+    //Test case 1.0: test constructor from effect type and get effect ID
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioEffect",
+            args = {UUID.class, UUID.class, int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test1_0ConstructorFromType() throws Exception {
+        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
+        assertTrue("no effects found", (desc.length != 0));
+        for (int i = 0; i < desc.length; i++) {
+            try {
+                AudioEffect effect = new AudioEffect(desc[i].mType,
+                        AudioEffect.EFFECT_TYPE_NULL,
+                        0,
+                        0);
+                assertNotNull("could not create AudioEffect", effect);
+                try {
+                    assertTrue("invalid effect ID", (effect.getId() != 0));
+                } catch (IllegalStateException e) {
+                    fail("AudioEffect not initialized");
+                } finally {
+                    effect.release();
+                }
+            } catch (IllegalArgumentException e) {
+                fail("Effect not found: "+desc[i].mName);
+            } catch (UnsupportedOperationException e) {
+                fail("Effect library not loaded");
+            }
+        }
+    }
+
+    //Test case 1.1: test constructor from effect uuid
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioEffect",
+            args = {UUID.class, UUID.class, int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test1_1ConstructorFromUuid() throws Exception {
+        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
+        assertTrue("no effects found", (desc.length != 0));
+        for (int i = 0; i < desc.length; i++) {
+            try {
+                AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_NULL,
+                        desc[i].mUuid,
+                        0,
+                        0);
+                assertNotNull("could not create AudioEffect", effect);
+                try {
+                    assertTrue("invalid effect ID", (effect.getId() != 0));
+                } catch (IllegalStateException e) {
+                    fail("AudioEffect not initialized");
+                } finally {
+                    effect.release();
+                }
+            } catch (IllegalArgumentException e) {
+                fail("Effect not found: "+desc[i].mName);
+            } catch (UnsupportedOperationException e) {
+                fail("Effect library not loaded");
+            }
+        }
+    }
+
+    //Test case 1.2: test constructor failure from unknown type
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioEffect",
+            args = {UUID.class, UUID.class, int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test1_2ConstructorUnknownType() throws Exception {
+
+        try {
+            AudioEffect effect = new AudioEffect(UUID.randomUUID(),
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    0,
+                    0);
+            fail("could create random AudioEffect");
+            if (effect != null) {
+                effect.release();
+            }
+        } catch (IllegalArgumentException e) {
+
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        }
+    }
+
+    //Test case 1.3: test getEnabled() failure when called on released effect
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioEffect",
+            args = {UUID.class, UUID.class, int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test1_3GetEnabledAfterRelease() throws Exception {
+
+        try {
+            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    0,
+                    0);
+            assertNotNull("could not create AudioEffect", effect);
+            effect.release();
+            try {
+                effect.getEnabled();
+                fail("getEnabled() processed after release()");
+            } catch (IllegalStateException e) {
+
+            }
+        } catch (IllegalArgumentException e) {
+            fail("AudioEffect not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        }
+    }
+
+    //Test case 1.4: test contructor on mediaPlayer audio session
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MediaPlayer.getAudioSessionId",
+            args = {}
+        )
+    })
+    public void test1_4InsertOnMediaPlayer() throws Exception {
+        MediaPlayer mp = new MediaPlayer();
+        assertNotNull("could not create mediaplayer", mp);
+        AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
+        mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+        afd.close();
+        getEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, mp.getAudioSessionId());
+        try {
+            mEffect.setEnabled(true);
+
+        } catch (IllegalStateException e) {
+            fail("AudioEffect not initialized");
+        } finally {
+            mp.release();
+            releaseEffect();
+        }
+    }
+
+    //Test case 1.5: test auxiliary effect attachement on MediaPlayer
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MediaPlayer.attachAuxEffect",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MediaPlayer.setAuxEffectSendLevel",
+            args = {}
+        )
+    })
+    public void test1_5AuxiliaryOnMediaPlayer() throws Exception {
+        createMediaPlayerLooper();
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);  // mMediaPlayer has been initialized?
+        mError = 0;
+
+        AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
+        mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+        afd.close();
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            synchronized(mLock) {
+                try {
+                    mMediaPlayer.attachAuxEffect(mEffect.getId());
+                    mMediaPlayer.setAuxEffectSendLevel(1.0f);
+                    mLock.wait(200);
+                } catch(Exception e) {
+                    fail("Attach effect: wait was interrupted.");
+                }
+            }
+            assertTrue("error on attachAuxEffect", mError == 0);
+
+        } catch (IllegalStateException e) {
+            fail("attach aux effect failed");
+        } finally {
+            terminateMediaPlayerLooper();
+            releaseEffect();
+        }
+    }
+
+    //Test case 1.6: test auxiliary effect attachement failure before setDatasource
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MediaPlayer.attachAuxEffect",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "MediaPlayer.setAuxEffectSendLevel",
+            args = {}
+        )
+    })
+    public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception {
+        createMediaPlayerLooper();
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);  // mMediaPlayer has been initialized?
+        mError = 0;
+
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            synchronized(mLock) {
+                try {
+                    mMediaPlayer.attachAuxEffect(mEffect.getId());
+                    mLock.wait(1000);
+                } catch(Exception e) {
+                    fail("Attach effect: wait was interrupted.");
+                }
+            }
+            assertTrue("no error on attachAuxEffect", mError != 0);
+
+        } catch (IllegalStateException e) {
+            fail("attach aux effect failed");
+        } finally {
+            terminateMediaPlayerLooper();
+            releaseEffect();
+        }
+    }
+
+
+    //Test case 1.7: test auxiliary effect attachement on AudioTrack
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioTrack.attachAuxEffect",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "AudioTrack.setAuxEffectSendLevel",
+            args = {}
+        )
+    })
+    public void test1_7AuxiliaryOnAudioTrack() throws Exception {
+        AudioTrack track = null;
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            track = new AudioTrack(
+                                AudioManager.STREAM_MUSIC,
+                                44100,
+                                AudioFormat.CHANNEL_OUT_MONO,
+                                AudioFormat.ENCODING_PCM_16BIT,
+                                AudioTrack.getMinBufferSize(44100,
+                                                            AudioFormat.CHANNEL_OUT_MONO,
+                                                            AudioFormat.ENCODING_PCM_16BIT),
+                                                            AudioTrack.MODE_STREAM);
+            assertNotNull("could not create AudioTrack", track);
+
+            int status = track.attachAuxEffect(mEffect.getId());
+            if (status != AudioTrack.SUCCESS) {
+                fail("could not attach aux effect");
+            }
+            status = track.setAuxEffectSendLevel(1.0f);
+            if (status != AudioTrack.SUCCESS) {
+                fail("could not set send level");
+            }
+        } catch (IllegalStateException e) {
+            fail("could not attach aux effect");
+        } catch (IllegalArgumentException e) {
+            fail("could not create AudioTrack");
+        } finally {
+            if (track != null) {
+                track.release();
+            }
+            releaseEffect();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - enable/ disable
+    //----------------------------------
+
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+
+        try {
+            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    0,
+                    0);
+            assertNotNull("could not create AudioEffect", effect);
+            try {
+                effect.setEnabled(true);
+                assertTrue("invalid state from getEnabled", effect.getEnabled());
+                effect.setEnabled(false);
+                assertFalse("invalid state to getEnabled", effect.getEnabled());
+
+            } catch (IllegalStateException e) {
+                fail("setEnabled() in wrong state");
+            } finally {
+                effect.release();
+            }
+        } catch (IllegalArgumentException e) {
+            fail("AudioEffect not found");
+
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+
+        try {
+            AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    0,
+                    0);
+            assertNotNull("could not create AudioEffect", effect);
+            effect.release();
+            try {
+                effect.setEnabled(true);
+                fail("setEnabled() processed after release");
+            } catch (IllegalStateException e) {
+                // test passed
+            }
+        } catch (IllegalArgumentException e) {
+            fail("AudioEffect not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 - set/get parameters
+    //----------------------------------
+
+    //Test case 3.0: test setParameter(byte[], byte[]) / getParameter(byte[], byte[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {byte[].class, byte[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {byte[].class, byte[].class}
+        )
+    })
+    public void test3_0SetParameterByteArrayByteArray() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            byte[] param = mEffect.intToByteArray(PresetReverb.PARAM_PRESET);
+            byte[] value = new byte[2];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            short preset = PresetReverb.PRESET_SMALLROOM;
+            if (mEffect.byteArrayToShort(value) == preset) {
+                preset = PresetReverb.PRESET_MEDIUMROOM;
+            }
+            value = mEffect.shortToByteArray(preset);
+            status = mEffect.setParameter(param, value);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            assertEquals("get/set Parameter failed", preset,
+                    mEffect.byteArrayToShort(value));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.1: test setParameter(int, int) / getParameter(int, int[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int.class, int[].class}
+        )
+    })
+    public void test3_1SetParameterIntInt() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
+        try {
+            int param = EnvironmentalReverb.PARAM_DECAY_TIME;
+            int[] value = new int[1];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            int time = 500;
+            if (value[0] == time) {
+                time = 1000;
+            }
+            status = mEffect.setParameter(param, time);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            assertTrue("got incorrect decay time",
+                    ((float)value[0] > (float)(time / DELAY_TOLERANCE)) &&
+                    ((float)value[0] < (float)(time * DELAY_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.2: test setParameter(int, short) / getParameter(int, short[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int.class, short[].class}
+        )
+    })
+    public void test3_2SetParameterIntShort() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            int param = PresetReverb.PARAM_PRESET;
+            short[] value = new short[1];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            short preset = PresetReverb.PRESET_SMALLROOM;
+            if (value[0] == preset) {
+                preset = PresetReverb.PRESET_MEDIUMROOM;
+            }
+            status = mEffect.setParameter(param, preset);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            assertEquals("get/set Parameter failed", preset, value[0]);
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.3: test setParameter(int, byte[]) / getParameter(int, byte[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, byte[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int.class, byte[].class}
+        )
+    })
+    public void test3_3SetParameterIntByteArray() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
+        try {
+            int param = EnvironmentalReverb.PARAM_DECAY_TIME;
+            byte[] value = new byte[4];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            int time = 500;
+            if (mEffect.byteArrayToInt(value) == time) {
+                time = 1000;
+            }
+            value = mEffect.intToByteArray(time);
+            status = mEffect.setParameter(param, value);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            int time2 = mEffect.byteArrayToInt(value);
+            assertTrue("got incorrect decay time",
+                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
+                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.4: test setParameter(int[], int[]) / getParameter(int[], int[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int[].class, int[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int[].class, int[].class}
+        )
+    })
+    public void test3_4SetParameterIntArrayIntArray() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
+        try {
+            int[] param = new int[1];
+            int[] value = new int[1];
+            param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            int[] time = new int[1];
+            time[0] = 500;
+            if (value[0] == time[0]) {
+                time[0] = 1000;
+            }
+            status = mEffect.setParameter(param, time);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            assertTrue("got incorrect decay time",
+                    ((float)value[0] > (float)(time[0] / DELAY_TOLERANCE)) &&
+                    ((float)value[0] < (float)(time[0] * DELAY_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.5: test setParameter(int[], short[]) / getParameter(int[], short[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int[].class, short[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int[].class, short[].class}
+        )
+    })
+
+    public void test3_5SetParameterIntArrayShortArray() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            int[] param = new int[1];
+            param[0] = PresetReverb.PARAM_PRESET;
+            short[] value = new short[1];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            short[] preset = new short[1];
+            preset[0] = PresetReverb.PRESET_SMALLROOM;
+            if (value[0] == preset[0]) {
+                preset[0] = PresetReverb.PRESET_MEDIUMROOM;
+            }
+            status = mEffect.setParameter(param, preset);
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            assertEquals("get/set Parameter failed", preset[0], value[0]);
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.6: test setParameter(int[], byte[]) / getParameter(int[], byte[])
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int[].class, byte[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int[].class, byte[].class}
+        )
+    })
+    public void test3_6SetParameterIntArrayByteArray() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
+        try {
+            int[] param = new int[1];
+            param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
+            byte[] value = new byte[4];
+            int status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
+            int time = 500;
+            if (mEffect.byteArrayToInt(value) == time) {
+                time = 1000;
+            }
+
+            status = mEffect.setParameter(param, mEffect.intToByteArray(time));
+            assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
+            status = mEffect.getParameter(param, value);
+            assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
+            int time2 = mEffect.byteArrayToInt(value);
+            assertTrue("got incorrect decay time",
+                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
+                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("setParameter() called in wrong state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+    //Test case 3.7: test setParameter() throws exception after release()
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, short.class}
+        )
+    })
+    public void test3_7SetParameterAfterRelease() throws Exception {
+        AudioEffect effect = null;
+        try {
+            effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
+                                    AudioEffect.EFFECT_TYPE_NULL,
+                                    0,
+                                    0);
+            assertNotNull("could not create AudioEffect", effect);
+            effect.release();
+            effect.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_SMALLROOM);
+            fail("setParameter() processed after release");
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("setParameter() rejected");
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            if (effect != null) {
+                effect.release();
+            }
+        }
+    }
+
+    //Test case 3.8: test getParameter() throws exception after release()
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, short[].class}
+        )
+    })
+    public void test3_8GetParameterAfterRelease() throws Exception {
+        AudioEffect effect = null;
+        try {
+            effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
+                                    AudioEffect.EFFECT_TYPE_NULL,
+                                    0,
+                                    0);
+            assertNotNull("could not create AudioEffect", effect);
+            effect.release();
+            short[] value = new short[1];
+            effect.getParameter(PresetReverb.PARAM_PRESET, value);
+            fail("getParameter() processed after release");
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("getParameter() rejected");
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            if (effect != null) {
+                effect.release();
+            }
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 4 priority and listeners
+    //----------------------------------
+
+    //Test case 4.0: test control passed to higher priority client
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "hasControl",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test4_0setEnabledLowerPriority() throws Exception {
+        AudioEffect effect1 = null;
+        AudioEffect effect2 = null;
+        try {
+            effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
+                                    AudioEffect.EFFECT_TYPE_NULL,
+                                    0,
+                                    0);
+            effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    1,
+                    0);
+
+            assertNotNull("could not create AudioEffect", effect1);
+            assertNotNull("could not create AudioEffect", effect2);
+
+            assertTrue("Effect2 does not have control", effect2.hasControl());
+            assertFalse("Effect1 has control", effect1.hasControl());
+            assertTrue("Effect1 can enable",
+                    effect1.setEnabled(true) == AudioEffect.ERROR_INVALID_OPERATION);
+            assertFalse("Effect1 has enabled", effect2.getEnabled());
+
+        } catch (IllegalArgumentException e) {
+            fail("Effect not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (effect1 != null) {
+                effect1.release();
+            }
+            if (effect2 != null) {
+                effect2.release();
+            }
+        }
+    }
+
+    //Test case 4.1: test control passed to higher priority client
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getParameter",
+            args = {int.class, short[].class}
+        )
+    })
+    public void test4_1setParameterLowerPriority() throws Exception {
+        AudioEffect effect1 = null;
+        AudioEffect effect2 = null;
+        try {
+            effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
+                                    AudioEffect.EFFECT_TYPE_NULL,
+                                    0,
+                                    0);
+            effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    1,
+                    0);
+
+            assertNotNull("could not create AudioEffect", effect1);
+            assertNotNull("could not create AudioEffect", effect2);
+
+            int status = effect2.setParameter(PresetReverb.PARAM_PRESET,
+                    PresetReverb.PRESET_SMALLROOM);
+            assertEquals("Effect2 setParameter failed",
+                    AudioEffect.SUCCESS, status);
+
+            status = effect1.setParameter(PresetReverb.PARAM_PRESET,
+                    PresetReverb.PRESET_MEDIUMROOM);
+            assertEquals("Effect1 setParameter did not fail",
+                    AudioEffect.ERROR_INVALID_OPERATION, status);
+
+            short[] value = new short[1];
+            status = effect2.getParameter(PresetReverb.PARAM_PRESET, value);
+            assertEquals("Effect2 getParameter failed",
+                    AudioEffect.SUCCESS, status);
+            assertEquals("Effect1 changed parameter", PresetReverb.PRESET_SMALLROOM
+                    , value[0]);
+
+
+        } catch (IllegalArgumentException e) {
+            fail("Effect not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (effect1 != null) {
+                effect1.release();
+            }
+            if (effect2 != null) {
+                effect2.release();
+            }
+        }
+    }
+
+    //Test case 4.2: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test4_2ControlStatusListener() throws Exception {
+
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Create second effect: wait was interrupted.");
+            } finally {
+                releaseEffect();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 4.3: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test4_3EnableStatusListener() throws Exception {
+
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mEffect2.setEnabled(true);
+        mIsEnabled = true;
+
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        assertTrue("effect not enabled", mEffect.getEnabled());
+        synchronized(mLock) {
+            try {
+                mEffect.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Second effect setEnabled: wait was interrupted.");
+            } finally {
+                releaseEffect();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 4.4: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {AudioEffect.OnParameterChangeListener.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameter",
+            args = {int.class, short.class}
+        )
+    })
+    public void test4_4ParameterChangedListener() throws Exception {
+
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        int status = mEffect2.setParameter(PresetReverb.PARAM_PRESET,
+                PresetReverb.PRESET_SMALLROOM);
+        assertEquals("mEffect2 setParameter failed",
+                AudioEffect.SUCCESS, status);
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mEffect.setParameter(PresetReverb.PARAM_PRESET,
+                        PresetReverb.PRESET_MEDIUMROOM);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                fail("set Parameter: wait was interrupted.");
+            } finally {
+                releaseEffect();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                PresetReverb.PARAM_PRESET, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // 5 command method
+    //----------------------------------
+
+
+    //Test case 5.0: test command method
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "command",
+            args = {int.class, byte[].class, byte[].class}
+        )
+    })
+    public void test5_0Command() throws Exception {
+        getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
+        try {
+            byte[] cmd = new byte[0];
+            byte[] reply = new byte[4];
+            // command 3 is ENABLE
+            int status = mEffect.command(3, cmd, reply);
+            assertEquals("command failed", AudioEffect.SUCCESS, status);
+            assertTrue("effect not enabled", mEffect.getEnabled());
+
+        } catch (IllegalStateException e) {
+            fail("command in illegal state");
+        } finally {
+            releaseEffect();
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getEffect(UUID type, int session) {
+         if (mEffect == null || session != mSession) {
+             if (session != mSession && mEffect != null) {
+                 mEffect.release();
+                 mEffect = null;
+             }
+             try {
+                 mEffect = new AudioEffect(type,
+                                             AudioEffect.EFFECT_TYPE_NULL,
+                                             0,
+                                             session);
+                 mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getEffect() AudioEffect not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getEffect() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mEffect", mEffect);
+    }
+
+    private void releaseEffect() {
+        if (mEffect != null) {
+            mEffect.release();
+            mEffect = null;
+        }
+    }
+
+    // Initializes the equalizer listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mEffect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
+                        AudioEffect.EFFECT_TYPE_NULL,
+                        0,
+                        0);
+                assertNotNull("could not create Equalizer2", mEffect2);
+
+                if (mControl) {
+                    mEffect2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mEffect2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mEffect2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mEffect2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mEffect2.setParameterListener(new AudioEffect.OnParameterChangeListener() {
+                        public void onParameterChange(AudioEffect effect, int status, byte[] param,
+                                byte[] value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mEffect2) {
+                                    mChangedParameter = mEffect2.byteArrayToInt(param);
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mEffect2 != null) {
+            mEffect2.release();
+            mEffect2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+    /*
+     * Initializes the message looper so that the MediaPlayer object can
+     * receive the callback messages.
+     */
+    private void createMediaPlayerLooper() {
+        mInitialized = false;
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by mMediaPlayer.
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mMediaPlayer = new MediaPlayer();
+                mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                    public boolean onError(MediaPlayer player, int what, int extra) {
+                        synchronized(mLock) {
+                            mError = what;
+                            mLock.notify();
+                        }
+                        return true;
+                    }
+                });
+                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                    public void onCompletion(MediaPlayer player) {
+                        synchronized(mLock) {
+                            mLock.notify();
+                        }
+                    }
+                });
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+    /*
+     * Terminates the message looper thread.
+     */
+    private void terminateMediaPlayerLooper() {
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+        if (mMediaPlayer != null) {
+            mMediaPlayer.release();
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/BassBoostTest.java b/tests/tests/media/src/android/media/cts/BassBoostTest.java
new file mode 100644
index 0000000..d0b16e4
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/BassBoostTest.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.BassBoost;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(BassBoost.class)
+public class BassBoostTest extends AndroidTestCase {
+
+    private String TAG = "BassBoostTest";
+    private final static short TEST_STRENGTH = 500;
+    private final static short TEST_STRENGTH2 = 1000;
+    private final static float STRENGTH_TOLERANCE = 1.1f;  // 10%
+
+    private BassBoost mBassBoost = null;
+    private BassBoost mBassBoost2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+
+    //-----------------------------------------------------------------
+    // BASS BOOST TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "BassBoost",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        BassBoost eq = null;
+        try {
+            eq = new BassBoost(0, 0);
+            assertNotNull("could not create BassBoost", eq);
+            try {
+                assertTrue("invalid effect ID", (eq.getId() != 0));
+            } catch (IllegalStateException e) {
+                fail("BassBoost not initialized");
+            }
+            // test passed
+        } catch (IllegalArgumentException e) {
+            fail("BassBoost not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test strength
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getStrengthSupported",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setStrength",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getRoundedStrength",
+            args = {}
+        )
+    })
+    public void test1_0Strength() throws Exception {
+        getBassBoost(0);
+        try {
+            if (mBassBoost.getStrengthSupported()) {
+                short strength = mBassBoost.getRoundedStrength();
+                strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
+                mBassBoost.setStrength((short)strength);
+                short strength2 = mBassBoost.getRoundedStrength();
+                // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
+                assertTrue("got incorrect strength",
+                        ((float)strength2 > (float)strength / STRENGTH_TOLERANCE) &&
+                        ((float)strength2 < (float)strength * STRENGTH_TOLERANCE));
+            } else {
+                short strength = mBassBoost.getRoundedStrength();
+                assertTrue("got incorrect strength", strength >= 0 && strength <= 1000);
+            }
+            // test passed
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseBassBoost();
+        }
+    }
+
+    //Test case 1.1: test properties
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperties",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperties",
+            args = {BassBoost.Settings.class}
+        )
+    })
+    public void test1_1Properties() throws Exception {
+        getBassBoost(0);
+        try {
+            BassBoost.Settings settings = mBassBoost.getProperties();
+            String str = settings.toString();
+            settings = new BassBoost.Settings(str);
+
+            short strength = settings.strength;
+            if (mBassBoost.getStrengthSupported()) {
+                strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
+            }
+            settings.strength = strength;
+            mBassBoost.setProperties(settings);
+            settings = mBassBoost.getProperties();
+
+            if (mBassBoost.getStrengthSupported()) {
+                // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
+                assertTrue("got incorrect strength",
+                        ((float)settings.strength > (float)strength / STRENGTH_TOLERANCE) &&
+                        ((float)settings.strength < (float)strength * STRENGTH_TOLERANCE));
+            }
+            // test passed
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseBassBoost();
+        }
+    }
+
+    //Test case 1.2: test setStrength() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setStrength",
+            args = {short.class}
+        )
+    })
+    public void test1_2SetStrengthAfterRelease() throws Exception {
+        getBassBoost(0);
+        mBassBoost.release();
+        try {
+            mBassBoost.setStrength(TEST_STRENGTH);
+            fail("setStrength() processed after release()");
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseBassBoost();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect enable/disable
+    //----------------------------------
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+        getBassBoost(0);
+        try {
+            mBassBoost.setEnabled(true);
+            assertTrue("invalid state from getEnabled", mBassBoost.getEnabled());
+            mBassBoost.setEnabled(false);
+            assertFalse("invalid state to getEnabled", mBassBoost.getEnabled());
+            // test passed
+        } catch (IllegalStateException e) {
+            fail("setEnabled() in wrong state");
+        } finally {
+            releaseBassBoost();
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+        getBassBoost(0);
+        mBassBoost.release();
+        try {
+            mBassBoost.setEnabled(true);
+            fail("setEnabled() processed after release()");
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseBassBoost();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 priority and listeners
+    //----------------------------------
+
+    //Test case 3.0: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test3_0ControlStatusListener() throws Exception {
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getBassBoost(0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseBassBoost();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 3.1: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        )
+    })
+    public void test3_1EnableStatusListener() throws Exception {
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mBassBoost2.setEnabled(true);
+        mIsEnabled = true;
+        getBassBoost(0);
+        synchronized(mLock) {
+            try {
+                mBassBoost.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseBassBoost();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 3.2: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {BassBoost.OnParameterChangeListener.class}
+        )
+    })
+    public void test3_2ParameterChangedListener() throws Exception {
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        getBassBoost(0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mBassBoost.setStrength(TEST_STRENGTH);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseBassBoost();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                BassBoost.PARAM_STRENGTH, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getBassBoost(int session) {
+         if (mBassBoost == null || session != mSession) {
+             if (session != mSession && mBassBoost != null) {
+                 mBassBoost.release();
+                 mBassBoost = null;
+             }
+             try {
+                mBassBoost = new BassBoost(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getBassBoost() BassBoost not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getBassBoost() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mBassBoost", mBassBoost);
+    }
+
+    private void releaseBassBoost() {
+        if (mBassBoost != null) {
+            mBassBoost.release();
+            mBassBoost = null;
+        }
+    }
+
+    // Initializes the bassboot listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mBassBoost2 = new BassBoost(0, 0);
+                assertNotNull("could not create bassboot2", mBassBoost2);
+
+                if (mControl) {
+                    mBassBoost2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mBassBoost2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mBassBoost2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mBassBoost2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mBassBoost2.setParameterListener(new BassBoost.OnParameterChangeListener() {
+                        public void onParameterChange(BassBoost effect, int status,
+                                int param, short value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mBassBoost2) {
+                                    mChangedParameter = param;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mBassBoost2 != null) {
+            mBassBoost2.release();
+            mBassBoost2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
new file mode 100644
index 0000000..b94da11
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.hardware.Camera;
+import android.media.CamcorderProfile;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.List;
+
+@TestTargetClass(CamcorderProfile.class)
+public class CamcorderProfileTest extends AndroidTestCase {
+
+    private static final String TAG = "CamcorderProfileTest";
+
+    private void checkProfile(CamcorderProfile profile) {
+        Log.v(TAG, String.format("profile: duration=%d, quality=%d, " +
+            "fileFormat=%d, videoCodec=%d, videoBitRate=%d, videoFrameRate=%d, " +
+            "videoFrameWidth=%d, videoFrameHeight=%d, audioCodec=%d, " +
+            "audioBitRate=%d, audioSampleRate=%d, audioChannels=%d",
+            profile.duration,
+            profile.quality,
+            profile.fileFormat,
+            profile.videoCodec,
+            profile.videoBitRate,
+            profile.videoFrameRate,
+            profile.videoFrameWidth,
+            profile.videoFrameHeight,
+            profile.audioCodec,
+            profile.audioBitRate,
+            profile.audioSampleRate,
+            profile.audioChannels));
+        assertTrue(profile.duration > 0);
+        assertTrue(profile.quality == CamcorderProfile.QUALITY_LOW ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH);
+        assertTrue(profile.videoBitRate > 0);
+        assertTrue(profile.videoFrameRate > 0);
+        assertTrue(profile.videoFrameWidth > 0);
+        assertTrue(profile.videoFrameHeight > 0);
+        assertTrue(profile.audioBitRate > 0);
+        assertTrue(profile.audioSampleRate > 0);
+        assertTrue(profile.audioChannels > 0);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "get",
+            args = {int.class}
+        )
+    })
+    public void testGet() {
+        CamcorderProfile lowProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
+        CamcorderProfile highProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
+        checkProfile(lowProfile);
+        checkProfile(highProfile);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "get",
+            args = {int.class, int.class}
+        )
+    })
+    public void testGetWithId() {
+        int nCamera = Camera.getNumberOfCameras();
+        for (int id = 0; id < nCamera; id++) {
+            CamcorderProfile lowProfile = CamcorderProfile.get(id,
+                    CamcorderProfile.QUALITY_LOW);
+            CamcorderProfile highProfile = CamcorderProfile.get(id,
+                    CamcorderProfile.QUALITY_HIGH);
+            checkProfile(lowProfile);
+            checkProfile(highProfile);
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/CameraProfileTest.java b/tests/tests/media/src/android/media/cts/CameraProfileTest.java
new file mode 100644
index 0000000..72cd296
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/CameraProfileTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.hardware.Camera;
+import android.media.CameraProfile;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.List;
+
+@TestTargetClass(CameraProfile.class)
+public class CameraProfileTest extends AndroidTestCase {
+
+    private static final String TAG = "CameraProfileTest";
+
+    private void checkQuality(int low, int mid, int high) {
+        Log.v(TAG, "low = " + low + ", mid = " + mid + ", high = " + high);
+        assertTrue(low >= 0 && low <= 100);
+        assertTrue(mid >= 0 && mid <= 100);
+        assertTrue(high >= 0 && high <= 100);
+        assertTrue(low <= mid && mid <= high);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getJpegEncodingQualityParameter",
+            args = {int.class}
+        )
+    })
+    public void testGetImageEncodingQualityParameter() {
+        int low = CameraProfile.getJpegEncodingQualityParameter(CameraProfile.QUALITY_LOW);
+        int mid = CameraProfile.getJpegEncodingQualityParameter(CameraProfile.QUALITY_MEDIUM);
+        int high = CameraProfile.getJpegEncodingQualityParameter(CameraProfile.QUALITY_HIGH);
+        checkQuality(low, mid, high);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getJpegEncodingQualityParameter",
+            args = {int.class, int.class}
+        )
+    })
+    public void testGetWithId() {
+        int nCamera = Camera.getNumberOfCameras();
+        for (int id = 0; id < nCamera; id++) {
+            int low = CameraProfile.getJpegEncodingQualityParameter(id, CameraProfile.QUALITY_LOW);
+            int mid = CameraProfile.getJpegEncodingQualityParameter(id, CameraProfile.QUALITY_MEDIUM);
+            int high = CameraProfile.getJpegEncodingQualityParameter(id, CameraProfile.QUALITY_HIGH);
+            checkQuality(low, mid, high);
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/EnvReverbTest.java b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
new file mode 100644
index 0000000..3854048
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.EnvironmentalReverb;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(EnvironmentalReverb.class)
+public class EnvReverbTest extends AndroidTestCase {
+
+    private String TAG = "EnvReverbTest";
+    private final static int MILLIBEL_TOLERANCE = 100;            // +/-1dB
+    private final static float DELAY_TOLERANCE = 1.05f;           // 5%
+    private final static float RATIO_TOLERANCE = 1.05f;           // 5%
+
+    private EnvironmentalReverb mReverb = null;
+    private EnvironmentalReverb mReverb2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+
+
+    //-----------------------------------------------------------------
+    // ENVIRONMENTAL REVERB TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "EnvironmentalReverb",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        EnvironmentalReverb envReverb = null;
+         try {
+            envReverb = new EnvironmentalReverb(0, 0);
+            assertNotNull("could not create EnvironmentalReverb", envReverb);
+            try {
+                assertTrue("invalid effect ID", (envReverb.getId() != 0));
+            } catch (IllegalStateException e) {
+                fail("EnvironmentalReverb not initialized");
+            }
+        } catch (IllegalArgumentException e) {
+            fail("EnvironmentalReverb not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (envReverb != null) {
+                envReverb.release();
+            }
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test room level and room HF level
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setRoomLevel",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getRoomLevel",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setRoomHFLevel",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getRoomHFLevel",
+            args = {}
+        )
+    })
+    public void test1_0Room() throws Exception {
+        getReverb(0);
+        try {
+            short level = mReverb.getRoomLevel();
+            level = (short)((level == 0) ? -1000 : 0);
+            mReverb.setRoomLevel(level);
+            short level2 = mReverb.getRoomLevel();
+            assertTrue("got incorrect room level",
+                    (level2 > (level - MILLIBEL_TOLERANCE)) &&
+                    (level2 < (level + MILLIBEL_TOLERANCE)));
+
+            level = mReverb.getRoomHFLevel();
+            level = (short)((level == 0) ? -1000 : 0);
+            mReverb.setRoomHFLevel(level);
+            level2 = mReverb.getRoomHFLevel();
+            assertTrue("got incorrect room HF level",
+                    (level2 > (level - MILLIBEL_TOLERANCE)) &&
+                    (level2 < (level + MILLIBEL_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 1.1: test decay time and ratio
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDecayTime",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDecayTime",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDecayHFRatio",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDecayHFRatio",
+            args = {}
+        )
+    })
+    public void test1_1Decay() throws Exception {
+        getReverb(0);
+        try {
+            int time = mReverb.getDecayTime();
+            time = (time == 500) ? 1000 : 500;
+            mReverb.setDecayTime(time);
+            int time2 = mReverb.getDecayTime();
+            assertTrue("got incorrect decay time",
+                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
+                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));
+            short ratio = mReverb.getDecayHFRatio();
+            ratio = (short)((ratio == 500) ? 1000 : 500);
+            mReverb.setDecayHFRatio(ratio);
+            short ratio2 = mReverb.getDecayHFRatio();
+            assertTrue("got incorrect decay HF ratio",
+                    ((float)ratio2 > (float)(ratio / RATIO_TOLERANCE)) &&
+                    ((float)ratio2 < (float)(ratio * RATIO_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+
+    //Test case 1.2: test reverb level and delay
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setReverbLevel",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getReverbLevel",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setReverbDelay",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getReverbDelay",
+            args = {}
+        )
+    })
+    public void test1_2Reverb() throws Exception {
+        getReverb(0);
+        try {
+            short level = mReverb.getReverbLevel();
+            level = (short)((level == 0) ? -1000 : 0);
+            mReverb.setReverbLevel(level);
+            short level2 = mReverb.getReverbLevel();
+            assertTrue("got incorrect reverb level",
+                    (level2 > (level - MILLIBEL_TOLERANCE)) &&
+                    (level2 < (level + MILLIBEL_TOLERANCE)));
+
+// FIXME:uncomment actual test when early reflections are implemented in the reverb
+//            int time = mReverb.getReverbDelay();
+//             mReverb.setReverbDelay(time);
+//            int time2 = mReverb.getReverbDelay();
+//            assertTrue("got incorrect reverb delay",
+//                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
+//                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));
+            mReverb.setReverbDelay(0);
+            int time2 = mReverb.getReverbDelay();
+            assertEquals("got incorrect reverb delay", mReverb.getReverbDelay(), 0);
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 1.3: test early reflections level and delay
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setReflectionsLevel",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getReflectionsLevel",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setReflectionsDelay",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getReflectionsDelay",
+            args = {}
+        )
+    })
+    public void test1_3Reflections() throws Exception {
+        getReverb(0);
+        try {
+// FIXME:uncomment actual test when early reflections are implemented in the reverb
+//            short level = mReverb.getReflectionsLevel();
+//            level = (short)((level == 0) ? -1000 : 0);
+//            mReverb.setReflectionsLevel(level);
+//            short level2 = mReverb.getReflectionsLevel();
+//            assertTrue("got incorrect reflections level",
+//                    (level2 > (level - MILLIBEL_TOLERANCE)) &&
+//                    (level2 < (level + MILLIBEL_TOLERANCE)));
+//
+//            int time = mReverb.getReflectionsDelay();
+//            time = (time == 20) ? 0 : 20;
+//            mReverb.setReflectionsDelay(time);
+//            int time2 = mReverb.getReflectionsDelay();
+//            assertTrue("got incorrect reflections delay",
+//                    ((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
+//                    ((float)time2 < (float)(time * DELAY_TOLERANCE)));
+            mReverb.setReflectionsLevel((short) 0);
+            assertEquals("got incorrect reverb delay",
+                    mReverb.getReflectionsLevel(), (short) 0);
+            mReverb.setReflectionsDelay(0);
+            assertEquals("got incorrect reverb delay",
+                    mReverb.getReflectionsDelay(), 0);
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 1.4: test diffusion and density
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDiffusion",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDiffusion",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDensity",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getDensity",
+            args = {}
+        )
+    })
+    public void test1_4DiffusionAndDensity() throws Exception {
+        getReverb(0);
+        try {
+            short ratio = mReverb.getDiffusion();
+            ratio = (short)((ratio == 500) ? 1000 : 500);
+            mReverb.setDiffusion(ratio);
+            short ratio2 = mReverb.getDiffusion();
+            assertTrue("got incorrect diffusion",
+                    ((float)ratio2 > (float)(ratio / RATIO_TOLERANCE)) &&
+                    ((float)ratio2 < (float)(ratio * RATIO_TOLERANCE)));
+
+            ratio = mReverb.getDensity();
+            ratio = (short)((ratio == 500) ? 1000 : 500);
+            mReverb.setDensity(ratio);
+            ratio2 = mReverb.getDensity();
+            assertTrue("got incorrect density",
+                    ((float)ratio2 > (float)(ratio / RATIO_TOLERANCE)) &&
+                    ((float)ratio2 < (float)(ratio * RATIO_TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 1.5: test properties
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperties",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperties",
+            args = {EnvironmentalReverb.Settings.class}
+        )
+    })
+    public void test1_5Properties() throws Exception {
+        getReverb(0);
+        try {
+            EnvironmentalReverb.Settings settings = mReverb.getProperties();
+            String str = settings.toString();
+            settings = new EnvironmentalReverb.Settings(str);
+            short level = (short)((settings.roomLevel == 0) ? -1000 : 0);
+            settings.roomLevel = level;
+            mReverb.setProperties(settings);
+            settings = mReverb.getProperties();
+            assertTrue("setProperties failed",
+                    (settings.roomLevel >= (level - MILLIBEL_TOLERANCE)) &&
+                    (settings.roomLevel <= (level + MILLIBEL_TOLERANCE)));
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect enable/disable
+    //----------------------------------
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+        getReverb(0);
+        try {
+            mReverb.setEnabled(true);
+            assertTrue("invalid state from getEnabled", mReverb.getEnabled());
+            mReverb.setEnabled(false);
+            assertFalse("invalid state to getEnabled", mReverb.getEnabled());
+        } catch (IllegalStateException e) {
+            fail("setEnabled() in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+        getReverb(0);
+        mReverb.release();
+        try {
+            mReverb.setEnabled(true);
+            fail("setEnabled() processed after release()");
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 priority and listeners
+    //----------------------------------
+
+    //Test case 3.0: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test3_0ControlStatusListener() throws Exception {
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getReverb(0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 3.1: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        )
+    })
+    public void test3_1EnableStatusListener() throws Exception {
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mReverb2.setEnabled(true);
+        mIsEnabled = true;
+        getReverb(0);
+        synchronized(mLock) {
+            try {
+                mReverb.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 3.2: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {EnvironmentalReverb.OnParameterChangeListener.class}
+        )
+    })
+    public void test3_2ParameterChangedListener() throws Exception {
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        getReverb(0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mReverb.setRoomLevel((short)0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                EnvironmentalReverb.PARAM_ROOM_LEVEL, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getReverb(int session) {
+         if (mReverb == null || session != mSession) {
+             if (session != mSession && mReverb != null) {
+                 mReverb.release();
+                 mReverb = null;
+             }
+             try {
+                mReverb = new EnvironmentalReverb(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getReverb() EnvironmentalReverb not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mReverb", mReverb);
+    }
+
+    private void releaseReverb() {
+        if (mReverb != null) {
+            mReverb.release();
+            mReverb = null;
+        }
+    }
+
+    // Initializes the reverb listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mReverb2 = new EnvironmentalReverb(0, 0);
+                assertNotNull("could not create reverb2", mReverb2);
+
+                if (mControl) {
+                    mReverb2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mReverb2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mReverb2.setParameterListener(new EnvironmentalReverb.OnParameterChangeListener() {
+                        public void onParameterChange(EnvironmentalReverb effect,
+                                int status, int param, int value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mChangedParameter = param;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mReverb2 != null) {
+            mReverb2.release();
+            mReverb2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/EqualizerTest.java b/tests/tests/media/src/android/media/cts/EqualizerTest.java
new file mode 100644
index 0000000..967a281
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/EqualizerTest.java
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.Equalizer;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(Equalizer.class)
+public class EqualizerTest extends AndroidTestCase {
+
+    private String TAG = "EqualizerTest";
+    private final static int MIN_NUMBER_OF_BANDS = 4;
+    private final static int MAX_LEVEL_RANGE_LOW = -1200;         // -12dB
+    private final static int MIN_LEVEL_RANGE_HIGH = 1200;         // +12dB
+    private final static int TEST_FREQUENCY_MILLIHERTZ = 1000000; // 1kHz
+    private final static int MIN_NUMBER_OF_PRESETS = 0;
+    private final static float TOLERANCE = 100;                   // +/-1dB
+
+    private Equalizer mEqualizer = null;
+    private Equalizer mEqualizer2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+
+
+    //-----------------------------------------------------------------
+    // EQUALIZER TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "Equalizer",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        Equalizer eq = null;
+        try {
+            eq = new Equalizer(0, 0);
+            assertNotNull("could not create Equalizer", eq);
+            try {
+                assertTrue("invalid effect ID", (eq.getId() != 0));
+            } catch (IllegalStateException e) {
+                fail("Equalizer not initialized");
+            }
+        } catch (IllegalArgumentException e) {
+            fail("Equalizer not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test setBandLevel() and getBandLevel()
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getNumberOfBands",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getBandLevelRange",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setBandLevel",
+            args = {short.class, short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getBandLevel",
+            args = {short.class}
+        )
+    })
+    public void test1_0BandLevel() throws Exception {
+        getEqualizer(0);
+        try {
+            short numBands = mEqualizer.getNumberOfBands();
+            assertTrue("not enough bands", numBands >= MIN_NUMBER_OF_BANDS);
+
+            short[] levelRange = mEqualizer.getBandLevelRange();
+            assertTrue("min level too high", levelRange[0] <= MAX_LEVEL_RANGE_LOW);
+            assertTrue("max level too low", levelRange[1] >= MIN_LEVEL_RANGE_HIGH);
+
+            mEqualizer.setBandLevel((short)0, levelRange[1]);
+            short level = mEqualizer.getBandLevel((short)0);
+            // allow +/- TOLERANCE margin on actual level compared to requested level
+            assertTrue("setBandLevel failed",
+                    (level >= (levelRange[1] - TOLERANCE)) &&
+                    (level <= (levelRange[1] + TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //Test case 1.1: test band frequency
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getBand",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getBandFreqRange",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCenterFreq",
+            args = {short.class}
+        )
+    })
+    public void test1_1BandFrequency() throws Exception {
+        getEqualizer(0);
+        try {
+            short band = mEqualizer.getBand(TEST_FREQUENCY_MILLIHERTZ);
+            assertTrue("getBand failed", band >= 0);
+            int[] freqRange = mEqualizer.getBandFreqRange(band);
+            assertTrue("getBandFreqRange failed",
+                    (freqRange[0] <= TEST_FREQUENCY_MILLIHERTZ) &&
+                    (freqRange[1] >= TEST_FREQUENCY_MILLIHERTZ));
+            int freq = mEqualizer.getCenterFreq(band);
+            assertTrue("getCenterFreq failed",
+                    (freqRange[0] <= freq) && (freqRange[1] >= freq));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //Test case 1.2: test presets
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getNumberOfPresets",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "usePreset",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCurrentPreset",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPresetName",
+            args = {short.class}
+        )
+    })
+    public void test1_2Presets() throws Exception {
+        getEqualizer(0);
+        try {
+            short numPresets = mEqualizer.getNumberOfPresets();
+            assertTrue("getNumberOfPresets failed", numPresets >= MIN_NUMBER_OF_PRESETS);
+            if (numPresets > 0) {
+                mEqualizer.usePreset((short)(numPresets - 1));
+                short preset = mEqualizer.getCurrentPreset();
+                assertEquals("usePreset failed", preset, (short)(numPresets - 1));
+                String name = mEqualizer.getPresetName(preset);
+                assertNotNull("getPresetName failed", name);
+            }
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //Test case 1.3: test properties
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperties",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperties",
+            args = {Equalizer.Settings.class}
+        )
+    })
+    public void test1_3Properties() throws Exception {
+        getEqualizer(0);
+        try {
+            Equalizer.Settings settings = mEqualizer.getProperties();
+            assertTrue("no enough bands", settings.numBands >= MIN_NUMBER_OF_BANDS);
+            short newLevel = 0;
+            if (settings.bandLevels[0] == 0) {
+                newLevel = -600;
+            }
+            String str = settings.toString();
+            settings = new Equalizer.Settings(str);
+            settings.curPreset = (short)-1;
+            settings.bandLevels[0] = newLevel;
+            mEqualizer.setProperties(settings);
+            settings = mEqualizer.getProperties();
+            assertTrue("setProperties failed",
+                    (settings.bandLevels[0] >= (newLevel - TOLERANCE)) &&
+                    (settings.bandLevels[0] <= (newLevel + TOLERANCE)));
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //Test case 1.4: test setBandLevel() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setBandLevel",
+            args = {short.class, short.class}
+        )
+    })
+    public void test1_4SetBandLevelAfterRelease() throws Exception {
+
+        getEqualizer(0);
+        mEqualizer.release();
+        try {
+            mEqualizer.setBandLevel((short)0, (short)0);
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect enable/disable
+    //----------------------------------
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+        getEqualizer(0);
+        try {
+            mEqualizer.setEnabled(true);
+            assertTrue("invalid state from getEnabled", mEqualizer.getEnabled());
+            mEqualizer.setEnabled(false);
+            assertFalse("invalid state to getEnabled", mEqualizer.getEnabled());
+
+        } catch (IllegalStateException e) {
+            fail("setEnabled() in wrong state");
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+
+        getEqualizer(0);
+        mEqualizer.release();
+        try {
+            mEqualizer.setEnabled(true);
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseEqualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 priority and listeners
+    //----------------------------------
+
+    //Test case 3.0: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test3_0ControlStatusListener() throws Exception {
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getEqualizer(0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseEqualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 3.1: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        )
+    })
+    public void test3_1EnableStatusListener() throws Exception {
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mEqualizer2.setEnabled(true);
+        mIsEnabled = true;
+        getEqualizer(0);
+        synchronized(mLock) {
+            try {
+                mEqualizer.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseEqualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 3.2: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {Equalizer.OnParameterChangeListener.class}
+        )
+    })
+    public void test3_2ParameterChangedListener() throws Exception {
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        getEqualizer(0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mEqualizer.setBandLevel((short)0, (short)0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseEqualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                Equalizer.PARAM_BAND_LEVEL, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getEqualizer(int session) {
+         if (mEqualizer == null || session != mSession) {
+             if (session != mSession && mEqualizer != null) {
+                 mEqualizer.release();
+                 mEqualizer = null;
+             }
+             try {
+                mEqualizer = new Equalizer(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getEqualizer() Equalizer not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getEqualizer() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mEqualizer", mEqualizer);
+    }
+
+    private void releaseEqualizer() {
+        if (mEqualizer != null) {
+            mEqualizer.release();
+            mEqualizer = null;
+        }
+    }
+
+    // Initializes the equalizer listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mEqualizer2 = new Equalizer(0, 0);
+                assertNotNull("could not create Equalizer2", mEqualizer2);
+
+                if (mControl) {
+                    mEqualizer2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mEqualizer2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mEqualizer2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mEqualizer2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mEqualizer2.setParameterListener(new Equalizer.OnParameterChangeListener() {
+                        public void onParameterChange(Equalizer effect,
+                                int status, int param1, int param2, int value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mEqualizer2) {
+                                    mChangedParameter = param1;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mEqualizer2 != null) {
+            mEqualizer2.release();
+            mEqualizer2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index e5dc1ff..db9c5be 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -38,8 +38,8 @@
 
     private final String OUTPUT_PATH;
     private static final int RECORD_TIME = 3000;
-    private static final int VIDEO_WIDTH = 320;
-    private static final int VIDEO_HEIGHT = 240;
+    private static final int VIDEO_WIDTH = 176;
+    private static final int VIDEO_HEIGHT = 144;
     private static final int FRAME_RATE = 15;
     private static final long MAX_FILE_SIZE = 5000;
     private static final int MAX_DURATION_MSEC = 200;
diff --git a/tests/tests/media/src/android/media/cts/PresetReverbTest.java b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
new file mode 100644
index 0000000..e29192b
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.PresetReverb;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(PresetReverb.class)
+public class PresetReverbTest extends AndroidTestCase {
+
+    private String TAG = "PresetReverbTest";
+    private final static short FIRST_PRESET = PresetReverb.PRESET_NONE;
+    private final static short LAST_PRESET = PresetReverb.PRESET_PLATE;
+    private PresetReverb mReverb = null;
+    private PresetReverb mReverb2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+
+
+    //-----------------------------------------------------------------
+    // PRESET REVERB TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "PresetReverb",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        PresetReverb reverb = null;
+        try {
+            reverb = new PresetReverb(0, 0);
+            assertNotNull("could not create PresetReverb", reverb);
+            try {
+                assertTrue("invalid effect ID", (reverb.getId() != 0));
+            } catch (IllegalStateException e) {
+                fail("PresetReverb not initialized");
+            }
+        } catch (IllegalArgumentException e) {
+            fail("PresetReverb not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (reverb != null) {
+                reverb.release();
+            }
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test presets
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setPreset",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getPreset",
+            args = {}
+        )
+    })
+    public void test1_0Presets() throws Exception {
+        getReverb(0);
+        try {
+            for (short preset = FIRST_PRESET;
+                 preset <= LAST_PRESET;
+                 preset++) {
+                mReverb.setPreset(preset);
+                assertEquals("got incorrect preset", preset, mReverb.getPreset());
+            }
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 1.1: test properties
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperties",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperties",
+            args = {PresetReverb.Settings.class}
+        )
+    })
+    public void test1_1Properties() throws Exception {
+        getReverb(0);
+        try {
+            PresetReverb.Settings settings = mReverb.getProperties();
+            String str = settings.toString();
+            settings = new PresetReverb.Settings(str);
+            short preset = (settings.preset == PresetReverb.PRESET_SMALLROOM) ?
+                            PresetReverb.PRESET_MEDIUMROOM : PresetReverb.PRESET_SMALLROOM;
+            settings.preset = preset;
+            mReverb.setProperties(settings);
+            settings = mReverb.getProperties();
+            assertEquals("setProperties failed", settings.preset, preset);
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect enable/disable
+    //----------------------------------
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+        getReverb(0);
+        try {
+            mReverb.setEnabled(true);
+            assertTrue("invalid state from getEnabled", mReverb.getEnabled());
+            mReverb.setEnabled(false);
+            assertFalse("invalid state to getEnabled", mReverb.getEnabled());
+        } catch (IllegalStateException e) {
+            fail("setEnabled() in wrong state");
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+        getReverb(0);
+        mReverb.release();
+        try {
+            mReverb.setEnabled(true);
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseReverb();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 priority and listeners
+    //----------------------------------
+
+    //Test case 3.0: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test3_0ControlStatusListener() throws Exception {
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getReverb(0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 3.1: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        )
+    })
+    public void test3_1EnableStatusListener() throws Exception {
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mReverb2.setEnabled(true);
+        mIsEnabled = true;
+        getReverb(0);
+        synchronized(mLock) {
+            try {
+                mReverb.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 3.2: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {PresetReverb.OnParameterChangeListener.class}
+        )
+    })
+    public void test3_2ParameterChangedListener() throws Exception {
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        getReverb(0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mReverb.setPreset(PresetReverb.PRESET_SMALLROOM);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseReverb();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                PresetReverb.PARAM_PRESET, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getReverb(int session) {
+         if (mReverb == null || session != mSession) {
+             if (session != mSession && mReverb != null) {
+                 mReverb.release();
+                 mReverb = null;
+             }
+             try {
+                mReverb = new PresetReverb(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getReverb() PresetReverb not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mReverb", mReverb);
+    }
+
+    private void releaseReverb() {
+        if (mReverb != null) {
+            mReverb.release();
+            mReverb = null;
+        }
+    }
+
+    // Initializes the reverb listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mReverb2 = new PresetReverb(0, 0);
+                assertNotNull("could not create Reverb2", mReverb2);
+
+                if (mControl) {
+                    mReverb2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mReverb2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mReverb2.setParameterListener(new PresetReverb.OnParameterChangeListener() {
+                        public void onParameterChange(PresetReverb effect,
+                                int status, int param, short value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mReverb2) {
+                                    mChangedParameter = param;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mReverb2 != null) {
+            mReverb2.release();
+            mReverb2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/VideoEditorTest.java b/tests/tests/media/src/android/media/cts/VideoEditorTest.java
new file mode 100644
index 0000000..481f4d6
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/VideoEditorTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import com.android.cts.stub.R;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class VideoEditorTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+
+    public VideoEditorTest() {
+        super(MediaStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        //setup for each test case.
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        //Test case clean up.
+        super.tearDown();
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/VirtualizerTest.java b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
new file mode 100644
index 0000000..07f8894
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.Virtualizer;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(Virtualizer.class)
+public class VirtualizerTest extends AndroidTestCase {
+
+    private String TAG = "VirtualizerTest";
+    private final static short TEST_STRENGTH = 500;
+    private final static short TEST_STRENGTH2 = 1000;
+    private final static float STRENGTH_TOLERANCE = 1.1f;  // 10%
+
+    private Virtualizer mVirtualizer = null;
+    private Virtualizer mVirtualizer2 = null;
+    private int mSession = -1;
+    private boolean mHasControl = false;
+    private boolean mIsEnabled = false;
+    private int mChangedParameter = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+
+    //-----------------------------------------------------------------
+    // VIRTUALIZER TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "Virtualizer",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getId",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        Virtualizer eq = null;
+        try {
+            eq = new Virtualizer(0, 0);
+            assertNotNull(" could not create Virtualizer", eq);
+            try {
+                assertTrue(" invalid effect ID", (eq.getId() != 0));
+            } catch (IllegalStateException e) {
+                fail("Virtualizer not initialized");
+            }
+        } catch (IllegalArgumentException e) {
+            fail("Virtualizer not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (eq != null) {
+                eq.release();
+            }
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test strength
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getStrengthSupported",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setStrength",
+            args = {short.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getRoundedStrength",
+            args = {}
+        )
+    })
+    public void test1_0Strength() throws Exception {
+        getVirtualizer(0);
+        try {
+            if (mVirtualizer.getStrengthSupported()) {
+                short strength = mVirtualizer.getRoundedStrength();
+                strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
+                mVirtualizer.setStrength((short)strength);
+                short strength2 = mVirtualizer.getRoundedStrength();
+                // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
+                assertTrue("got incorrect strength",
+                        ((float)strength2 > (float)strength / STRENGTH_TOLERANCE) &&
+                        ((float)strength2 < (float)strength * STRENGTH_TOLERANCE));
+            } else {
+                short strength = mVirtualizer.getRoundedStrength();
+                assertTrue("got incorrect strength", strength >= 0 && strength <= 1000);
+            }
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseVirtualizer();
+        }
+    }
+
+    //Test case 1.1: test properties
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getProperties",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setProperties",
+            args = {Virtualizer.Settings.class}
+        )
+    })
+    public void test1_1Properties() throws Exception {
+        getVirtualizer(0);
+        try {
+            Virtualizer.Settings settings = mVirtualizer.getProperties();
+            String str = settings.toString();
+            settings = new Virtualizer.Settings(str);
+
+            short strength = settings.strength;
+            if (mVirtualizer.getStrengthSupported()) {
+                strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
+            }
+            settings.strength = strength;
+            mVirtualizer.setProperties(settings);
+            settings = mVirtualizer.getProperties();
+
+            if (mVirtualizer.getStrengthSupported()) {
+                // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
+                assertTrue("got incorrect strength",
+                        ((float)settings.strength > (float)strength / STRENGTH_TOLERANCE) &&
+                        ((float)settings.strength < (float)strength * STRENGTH_TOLERANCE));
+            }
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseVirtualizer();
+        }
+    }
+
+    //Test case 1.2: test setStrength() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setStrength",
+            args = {short.class}
+        )
+    })
+    public void test1_2SetStrengthAfterRelease() throws Exception {
+        getVirtualizer(0);
+        mVirtualizer.release();
+        try {
+            mVirtualizer.setStrength(TEST_STRENGTH);
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseVirtualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect enable/disable
+    //----------------------------------
+
+    //Test case 2.0: test setEnabled() and getEnabled() in valid state
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        )
+    })
+    public void test2_0SetEnabledGetEnabled() throws Exception {
+        getVirtualizer(0);
+        try {
+            mVirtualizer.setEnabled(true);
+            assertTrue(" invalid state from getEnabled", mVirtualizer.getEnabled());
+            mVirtualizer.setEnabled(false);
+            assertFalse(" invalid state to getEnabled", mVirtualizer.getEnabled());
+        } catch (IllegalStateException e) {
+            fail("setEnabled() in wrong state");
+        } finally {
+            releaseVirtualizer();
+        }
+    }
+
+    //Test case 2.1: test setEnabled() throws exception after release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        )
+    })
+    public void test2_1SetEnabledAfterRelease() throws Exception {
+        getVirtualizer(0);
+        mVirtualizer.release();
+        try {
+            mVirtualizer.setEnabled(true);
+        } catch (IllegalStateException e) {
+            // test passed
+        } finally {
+            releaseVirtualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 3 priority and listeners
+    //----------------------------------
+
+    //Test case 3.0: test control status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setControlStatusListener",
+            args = {AudioEffect.OnControlStatusChangeListener.class}
+        )
+    })
+    public void test3_0ControlStatusListener() throws Exception {
+        mHasControl = true;
+        createListenerLooper(true, false, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        synchronized(mLock) {
+            try {
+                getVirtualizer(0);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseVirtualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("effect control not lost by effect1", mHasControl);
+    }
+
+    //Test case 3.1: test enable status listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnableStatusListener",
+            args = {AudioEffect.OnEnableStatusChangeListener.class}
+        )
+    })
+    public void test3_1EnableStatusListener() throws Exception {
+        createListenerLooper(false, true, false);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        mVirtualizer2.setEnabled(true);
+        mIsEnabled = true;
+        getVirtualizer(0);
+        synchronized(mLock) {
+            try {
+                mVirtualizer.setEnabled(false);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseVirtualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertFalse("enable status not updated", mIsEnabled);
+    }
+
+    //Test case 3.2: test parameter changed listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setParameterListener",
+            args = {Virtualizer.OnParameterChangeListener.class}
+        )
+    })
+    public void test3_2ParameterChangedListener() throws Exception {
+        createListenerLooper(false, false, true);
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Looper creation: wait was interrupted.");
+            }
+        }
+        assertTrue(mInitialized);
+        getVirtualizer(0);
+        synchronized(mLock) {
+            try {
+                mChangedParameter = -1;
+                mVirtualizer.setStrength(TEST_STRENGTH);
+                mLock.wait(1000);
+            } catch(Exception e) {
+                Log.e(TAG, "Create second effect: wait was interrupted.");
+            } finally {
+                releaseVirtualizer();
+                terminateListenerLooper();
+            }
+        }
+        assertEquals("parameter change not received",
+                Virtualizer.PARAM_STRENGTH, mChangedParameter);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getVirtualizer(int session) {
+         if (mVirtualizer == null || session != mSession) {
+             if (session != mSession && mVirtualizer != null) {
+                 mVirtualizer.release();
+                 mVirtualizer = null;
+             }
+             try {
+                mVirtualizer = new Virtualizer(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getVirtualizer() Virtualizer not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getVirtualizer() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mVirtualizer", mVirtualizer);
+    }
+
+    private void releaseVirtualizer() {
+        if (mVirtualizer != null) {
+            mVirtualizer.release();
+            mVirtualizer = null;
+        }
+    }
+
+    // Initializes the virtualizer listener looper
+    class ListenerThread extends Thread {
+        boolean mControl;
+        boolean mEnable;
+        boolean mParameter;
+
+        public ListenerThread(boolean control, boolean enable, boolean parameter) {
+            super();
+            mControl = control;
+            mEnable = enable;
+            mParameter = parameter;
+        }
+    }
+
+    private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
+        mInitialized = false;
+        new ListenerThread(control, enable, parameter) {
+            @Override
+            public void run() {
+                // Set up a looper
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                mVirtualizer2 = new Virtualizer(0, 0);
+                assertNotNull("could not create virtualizer2", mVirtualizer2);
+
+                if (mControl) {
+                    mVirtualizer2.setControlStatusListener(
+                            new AudioEffect.OnControlStatusChangeListener() {
+                        public void onControlStatusChange(
+                                AudioEffect effect, boolean controlGranted) {
+                            synchronized(mLock) {
+                                if (effect == mVirtualizer2) {
+                                    mHasControl = controlGranted;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mEnable) {
+                    mVirtualizer2.setEnableStatusListener(
+                            new AudioEffect.OnEnableStatusChangeListener() {
+                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                            synchronized(mLock) {
+                                if (effect == mVirtualizer2) {
+                                    mIsEnabled = enabled;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+                if (mParameter) {
+                    mVirtualizer2.setParameterListener(new Virtualizer.OnParameterChangeListener() {
+                        public void onParameterChange(Virtualizer effect, int status,
+                                int param, short value)
+                        {
+                            synchronized(mLock) {
+                                if (effect == mVirtualizer2) {
+                                    mChangedParameter = param;
+                                    mLock.notify();
+                                }
+                            }
+                        }
+                    });
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+
+    // Terminates the listener looper thread.
+    private void terminateListenerLooper() {
+        if (mVirtualizer2 != null) {
+            mVirtualizer2.release();
+            mVirtualizer2 = null;
+        }
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/VisualizerTest.java b/tests/tests/media/src/android/media/cts/VisualizerTest.java
new file mode 100644
index 0000000..d23be3f
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/VisualizerTest.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.AudioEffect;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.Visualizer;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+@TestTargetClass(Visualizer.class)
+public class VisualizerTest extends AndroidTestCase {
+
+    private String TAG = "VisualizerTest";
+    private final static int MIN_CAPTURE_RATE_MAX = 10000; // 10Hz
+    private final static int MIN_CAPTURE_SIZE_MAX = 1024;
+    private final static int MAX_CAPTURE_SIZE_MIN = 512;
+
+    private Visualizer mVisualizer = null;
+    private int mSession = -1;
+    private boolean mInitialized = false;
+    private Looper mLooper = null;
+    private final Object mLock = new Object();
+    private byte[] mWaveform = null;
+    private byte[] mFft = null;
+    private boolean mCaptureWaveform = false;
+    private boolean mCaptureFft = false;
+
+    //-----------------------------------------------------------------
+    // VISUALIZER TESTS:
+    //----------------------------------
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "Visualizer",
+            args = {int.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "release",
+            args = {}
+        )
+    })
+    public void test0_0ConstructorAndRelease() throws Exception {
+        Visualizer visualizer = null;
+         try {
+            visualizer = new Visualizer(0);
+            assertNotNull("could not create Visualizer", visualizer);
+        } catch (IllegalArgumentException e) {
+            fail("Visualizer not found");
+        } catch (UnsupportedOperationException e) {
+            fail("Effect library not loaded");
+        } finally {
+            if (visualizer != null) {
+                visualizer.release();
+            }
+        }
+    }
+
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: capture rates
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getMaxCaptureRate",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getSamplingRate",
+            args = {}
+        )
+    })
+    public void test1_0CaptureRates() throws Exception {
+        getVisualizer(0);
+        try {
+            int captureRate = mVisualizer.getMaxCaptureRate();
+            assertTrue("insufficient max capture rate",
+                    captureRate >= MIN_CAPTURE_RATE_MAX);
+            int samplingRate = mVisualizer.getSamplingRate();
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseVisualizer();
+        }
+    }
+
+    //Test case 1.1: test capture size
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCaptureSizeRange",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setCaptureSize",
+            args = {int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getCaptureSize",
+            args = {}
+        )
+    })
+    public void test1_1CaptureSize() throws Exception {
+        getVisualizer(0);
+        try {
+            int[] range = mVisualizer.getCaptureSizeRange();
+            assertTrue("insufficient min capture size",
+                    range[0] <= MAX_CAPTURE_SIZE_MIN);
+            assertTrue("insufficient min capture size",
+                    range[1] >= MIN_CAPTURE_SIZE_MAX);
+            mVisualizer.setCaptureSize(range[0]);
+            assertEquals("insufficient min capture size",
+                    range[0], mVisualizer.getCaptureSize());
+            mVisualizer.setCaptureSize(range[1]);
+            assertEquals("insufficient min capture size",
+                    range[1], mVisualizer.getCaptureSize());
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } finally {
+            releaseVisualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - check capture
+    //----------------------------------
+
+    //Test case 2.0: test cature in polling mode
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getWaveForm",
+            args = {byte[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getFft",
+            args = {byte[].class}
+        )
+    })
+    public void test2_0PollingCapture() throws Exception {
+        try {
+            getVisualizer(0);
+            mVisualizer.setEnabled(true);
+            assertTrue("visualizer not enabled", mVisualizer.getEnabled());
+            Thread.sleep(100);
+            // check capture on silence
+            byte[] data = new byte[mVisualizer.getCaptureSize()];
+            mVisualizer.getWaveForm(data);
+            int energy = computeEnergy(data, true);
+            assertEquals("getWaveForm reports energy for silence",
+                    0, energy);
+            mVisualizer.getFft(data);
+            energy = computeEnergy(data, false);
+            assertEquals("getFft reports energy for silence",
+                    0, energy);
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            fail("sleep() interrupted");
+        }
+        finally {
+            releaseVisualizer();
+        }
+    }
+
+    //Test case 2.1: test capture with listener
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setEnabled",
+            args = {boolean.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getEnabled",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "setDataCaptureListener",
+            args = {Visualizer.OnDataCaptureListener.class,
+                    int.class, boolean.class, boolean.class}
+        )
+    })
+    public void test2_1ListenerCapture() throws Exception {
+        try {
+            getVisualizer(0);
+            createListenerLooper();
+            synchronized(mLock) {
+                try {
+                    mLock.wait(1000);
+                } catch(Exception e) {
+                    Log.e(TAG, "Looper creation: wait was interrupted.");
+                }
+            }
+            assertTrue(mInitialized);
+
+            mVisualizer.setEnabled(true);
+            assertTrue("visualizer not enabled", mVisualizer.getEnabled());
+
+            Thread.sleep(100);
+            // check capture on silence
+            synchronized(mLock) {
+                try {
+                    mCaptureWaveform = true;
+                    mLock.wait(1000);
+                    mCaptureWaveform = false;
+                } catch(Exception e) {
+                    Log.e(TAG, "Capture waveform: wait was interrupted.");
+                }
+            }
+            assertNotNull("waveform capture failed", mWaveform);
+            int energy = computeEnergy(mWaveform, true);
+            assertEquals("getWaveForm reports energy for silence",
+                    0, energy);
+
+            synchronized(mLock) {
+                try {
+                    mCaptureFft = true;
+                    mLock.wait(1000);
+                    mCaptureFft = false;
+                } catch(Exception e) {
+                    Log.e(TAG, "Capture FFT: wait was interrupted.");
+                }
+            }
+            assertNotNull("FFT capture failed", mFft);
+            energy = computeEnergy(mFft, false);
+            assertEquals("getFft reports energy for silence",
+                    0, energy);
+
+        } catch (IllegalArgumentException e) {
+            fail("Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            fail("get parameter() rejected");
+        } catch (IllegalStateException e) {
+            fail("get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            fail("sleep() interrupted");
+        } finally {
+            terminateListenerLooper();
+            releaseVisualizer();
+        }
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private int computeEnergy(byte[] data, boolean pcm) {
+        int energy = 0;
+        if (data.length != 0) {
+            if (pcm) {
+                for (int i = 0; i < data.length; i++) {
+                    int tmp = ((int)data[i] & 0xFF) - 128;
+                    energy += tmp*tmp;
+                }
+            } else {
+                energy = (int)data[0] * (int)data[0];
+                for (int i = 2; i < data.length; i += 2) {
+                    int real = (int)data[i];
+                    int img = (int)data[i + 1];
+                    energy += real * real + img * img;
+                }
+            }
+        }
+        return energy;
+    }
+
+    private void getVisualizer(int session) {
+         if (mVisualizer == null || session != mSession) {
+             if (session != mSession && mVisualizer != null) {
+                 mVisualizer.release();
+                 mVisualizer = null;
+             }
+             try {
+                mVisualizer = new Visualizer(session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getVisualizer() Visualizer not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getVisualizer() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mVisualizer", mVisualizer);
+    }
+
+    private void releaseVisualizer() {
+        if (mVisualizer != null) {
+            mVisualizer.release();
+            mVisualizer = null;
+        }
+   }
+
+    private void createListenerLooper() {
+
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by mEffect.
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                if (mVisualizer != null) {
+                    mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
+                        public void onWaveFormDataCapture(
+                                Visualizer visualizer, byte[] waveform, int samplingRate) {
+                            synchronized(mLock) {
+                                if (visualizer == mVisualizer) {
+                                    if (mCaptureWaveform) {
+                                        mWaveform = waveform;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        }
+
+                        public void onFftDataCapture(
+                                Visualizer visualizer, byte[] fft, int samplingRate) {
+                            synchronized(mLock) {
+                                if (visualizer == mVisualizer) {
+                                    if (mCaptureFft) {
+                                        mFft = fft;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    10000,
+                    true,
+                    true);
+                }
+
+                synchronized(mLock) {
+                    mInitialized = true;
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+    }
+    /*
+     * Terminates the listener looper thread.
+     */
+    private void terminateListenerLooper() {
+        if (mLooper != null) {
+            mLooper.quit();
+            mLooper = null;
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index 086397a..50fe749 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -51,9 +51,12 @@
 
     private static final Pattern DEVICE_PATTERN =
         Pattern.compile("^([0-9a-z_]+)$");
+    private static final Pattern SERIAL_NUMBER_PATTERN =
+        Pattern.compile("^([0-9A-Za-z]{0,20})$");
 
     /** Tests that check for valid values of constants in Build. */
     public void testBuildConstants() {
+        assertTrue(SERIAL_NUMBER_PATTERN.matcher(Build.SERIAL).matches());
         assertTrue(DEVICE_PATTERN.matcher(Build.DEVICE).matches());
     }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/SettingsTest.java b/tests/tests/provider/src/android/provider/cts/SettingsTest.java
index e3ca242..73fd836 100644
--- a/tests/tests/provider/src/android/provider/cts/SettingsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SettingsTest.java
@@ -28,10 +28,10 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 @TestTargetClass(android.provider.Settings.class)
 public class SettingsTest extends AndroidTestCase {
-
     public void testSystemTable() throws RemoteException {
         final String[] SYSTEM_PROJECTION = new String[] {
                 Settings.System._ID, Settings.System.NAME, Settings.System.VALUE
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
index 3f75f94..a97aa96 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -17,12 +17,15 @@
 package android.telephony.cts;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.SystemClock;
 import android.telephony.TelephonyManager;
 import android.telephony.SmsManager;
 import android.test.AndroidTestCase;
@@ -50,6 +53,12 @@
     private static final String SMS_SEND_ACTION = "CTS_SMS_SEND_ACTION";
     private static final String SMS_DELIVERY_ACTION = "CTS_SMS_DELIVERY_ACTION";
 
+    // List of network operators that don't support SMS delivery report
+    private static final List<String> NO_DELIVERY_REPORTS =
+            Arrays.asList(
+                    "310410"    // AT&T Mobility
+            );
+
     private TelephonyManager mTelephonyManager;
     private String mDestAddr;
     private String mText;
@@ -59,6 +68,7 @@
     private PendingIntent mDeliveredIntent;
     private Intent mSendIntent;
     private Intent mDeliveryIntent;
+    private boolean mDeliveryReportSupported;
 
     private static final int TIME_OUT = 1000 * 60 * 4;
 
@@ -69,6 +79,18 @@
             (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
         mDestAddr = mTelephonyManager.getLine1Number();
         mText = "This is a test message";
+
+        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            // CDMA supports SMS delivery report
+            mDeliveryReportSupported = true;
+        } else if (mTelephonyManager.getDeviceId().equals("000000000000000")) {
+            // emulator doesn't support SMS delivery report
+            mDeliveryReportSupported = false;
+        } else {
+            // is this a GSM network that doesn't support SMS delivery report?
+            String mccmnc = mTelephonyManager.getSimOperator();
+            mDeliveryReportSupported = !(NO_DELIVERY_REPORTS.contains(mccmnc));
+        }
     }
 
     @TestTargetNew(
@@ -120,8 +142,10 @@
         // send single text sms
         init();
         sendTextMessage(mDestAddr, mDestAddr, mSentIntent, mDeliveredIntent);
-        mSendReceiver.waitForCalls(1, TIME_OUT);
-        mDeliveryReceiver.waitForCalls(1, TIME_OUT);
+        assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
+        if (mDeliveryReportSupported) {
+            assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
+        }
 
         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
             // TODO: temp workaround, OCTET encoding for EMS not properly supported
@@ -134,8 +158,10 @@
 
         init();
         sendDataMessage(mDestAddr, port, data, mSentIntent, mDeliveredIntent);
-        mSendReceiver.waitForCalls(1, TIME_OUT);
-        mDeliveryReceiver.waitForCalls(1, TIME_OUT);
+        assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
+        if (mDeliveryReportSupported) {
+            assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
+        }
 
         // send multi parts text sms
         init();
@@ -148,8 +174,10 @@
             deliveryIntents.add(PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent, 0));
         }
         sendMultiPartTextMessage(mDestAddr, parts, sentIntents, deliveryIntents);
-        mSendReceiver.waitForCalls(numParts, TIME_OUT);
-        mDeliveryReceiver.waitForCalls(numParts, TIME_OUT);
+        assertTrue(mSendReceiver.waitForCalls(numParts, TIME_OUT));
+        if (mDeliveryReportSupported) {
+            assertTrue(mDeliveryReceiver.waitForCalls(numParts, TIME_OUT));
+        }
     }
 
     private void init() {
@@ -220,12 +248,20 @@
             }
         }
 
-        public void waitForCalls(int expectedCalls, long timeout) throws InterruptedException {
+        public boolean waitForCalls(int expectedCalls, long timeout) throws InterruptedException {
             synchronized(mLock) {
                 mExpectedCalls = expectedCalls;
-                if (mCalls < mExpectedCalls) {
-                    mLock.wait(timeout);
+                long startTime = SystemClock.elapsedRealtime();
+
+                while (mCalls < mExpectedCalls) {
+                    long waitTime = timeout - (SystemClock.elapsedRealtime() - startTime);
+                    if (waitTime > 0) {
+                        mLock.wait(waitTime);
+                    } else {
+                        return false;  // timed out
+                    }
                 }
+                return true;  // success
             }
         }
     }
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
index 44b0871..515f8b5 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsMessageTest.java
@@ -212,7 +212,7 @@
         assertEquals(SCA2, sms.getServiceCenterAddress());
         assertEquals(OA2, sms.getOriginatingAddress());
         assertEquals(MESSAGE_BODY2, sms.getMessageBody());
-        CharSequence msgBody = (CharSequence) sms.getMessageBody();
+        CharSequence msgBody = sms.getMessageBody();
         result = SmsMessage.calculateLength(msgBody, false);
         assertEquals(SMS_NUMBER2, result[0]);
         assertEquals(sms.getMessageBody().length(), result[1]);
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index ebc33a6..deed336 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -21,14 +21,12 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.os.Looper;
 import android.os.cts.TestThread;
-import android.provider.Settings;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
@@ -298,7 +296,7 @@
 
             case TelephonyManager.PHONE_TYPE_NONE:
                 assertNull(deviceId);
-                assertHardwareId();
+                assertSerialNumber();
                 assertMacAddressReported();
                 break;
 
@@ -395,15 +393,13 @@
                 Pattern.matches(meidPattern, deviceId));
     }
 
-    private void assertHardwareId() {
-        ContentResolver resolver = mContext.getContentResolver();
-        String hardwareId = Settings.Secure.getString(resolver, "hardware_id");
-        assertNotNull("Non-telephony devices must define a Settings.Secure 'hardware_id' property.",
-                hardwareId);
+    private void assertSerialNumber() {
+        assertNotNull("Non-telephony devices must have a Build.SERIAL number.",
+                Build.SERIAL);
         assertTrue("Hardware id must be no longer than 20 characters.",
-                hardwareId.length() <= 20);
+                Build.SERIAL.length() <= 20);
         assertTrue("Hardware id must be alphanumeric.",
-                Pattern.matches("[0-9A-Za-z]+", hardwareId));
+                Pattern.matches("[0-9A-Za-z]+", Build.SERIAL));
     }
 
     private void assertMacAddressReported() {
diff --git a/tests/tests/telephony/src/android/telephony/gsm/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/gsm/cts/SmsManagerTest.java
index 8dc6936..512e89d 100644
--- a/tests/tests/telephony/src/android/telephony/gsm/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/gsm/cts/SmsManagerTest.java
@@ -28,6 +28,7 @@
 @TestTargetClass(SmsManager.class)
 public class SmsManagerTest extends android.telephony.cts.SmsManagerTest {
 
+    @Override
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "getDefault",
diff --git a/tests/tests/util/src/android/util/cts/TimeUtilsTest.java b/tests/tests/util/src/android/util/cts/TimeUtilsTest.java
index 8a720ef..47e37a0 100644
--- a/tests/tests/util/src/android/util/cts/TimeUtilsTest.java
+++ b/tests/tests/util/src/android/util/cts/TimeUtilsTest.java
@@ -21,8 +21,6 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
-import org.apache.harmony.luni.internal.util.ZoneInfoDB;
-
 import android.util.TimeUtils;
 
 import java.util.Calendar;
@@ -473,20 +471,6 @@
         }
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            notes = "Test method: getTimeZoneDatabaseVersion",
-            method = "getTimeZoneDatabaseVersion",
-            args = {}
-        )
-    })
-    public void testGetTimeZoneDatabaseVersion(){
-        String version = TimeUtils.getTimeZoneDatabaseVersion();
-        assertTrue(5 == version.length());
-        assertEquals(ZoneInfoDB.getVersion(), version);
-    }
-
     private static TimeZone guessTimeZone(Calendar c, String country) {
         return TimeUtils.getTimeZone(c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET),
                                      c.get(Calendar.DST_OFFSET) != 0,
diff --git a/tests/tests/view/src/android/view/cts/MotionEventTest.java b/tests/tests/view/src/android/view/cts/MotionEventTest.java
index beece1e..e4df594 100644
--- a/tests/tests/view/src/android/view/cts/MotionEventTest.java
+++ b/tests/tests/view/src/android/view/cts/MotionEventTest.java
@@ -488,5 +488,13 @@
         assertEquals(1, mMotionEvent2.getHistorySize());
 
         mMotionEvent2.recycle();
+        
+        try {
+            mMotionEvent2.recycle();
+            fail("recycle() should throw an exception when the event has already been recycled.");
+        } catch (RuntimeException ex) {
+        }
+        
+        mMotionEvent2 = null; // since it was recycled, don't try to recycle again in tear down
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index 527f444..0e31888 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -39,11 +39,13 @@
 import android.util.DisplayMetrics;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.Gravity;
+import android.view.InputQueue;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
@@ -1243,6 +1245,14 @@
         public void setDefaultWindowFormat(int format) {
             super.setDefaultWindowFormat(format);
         }
+        
+        @Override
+        public void takeSurface(SurfaceHolder.Callback2 callback) {
+        }
+        
+        @Override
+        public void takeInputQueue(InputQueue.Callback callback) {
+        }
     }
 
     private class MockWindowCallback implements Window.Callback {
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
index 896e99f..bdee05a 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
@@ -97,6 +97,11 @@
             args = {int.class, int.class}
         ),
         @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "getSelectedText",
+                args = {int.class}
+            ),
+        @TestTargetNew(
             level = TestLevel.COMPLETE,
             method = "getCursorCapsMode",
             args = {int.class}
@@ -127,6 +132,11 @@
             args = {CharSequence.class, int.class}
         ),
         @TestTargetNew(
+                level = TestLevel.COMPLETE,
+                method = "setComposingRegion",
+                args = {int.class, int.class}
+            ),
+        @TestTargetNew(
             level = TestLevel.COMPLETE,
             method = "sendKeyEvent",
             args = {KeyEvent.class}
@@ -184,6 +194,10 @@
         assertTrue(inputConnection.isSetComposingTextCalled);
         wrapper.setSelection(0, 10);
         assertTrue(inputConnection.isSetSelectionCalled);
+        wrapper.getSelectedText(0);
+        assertTrue(inputConnection.isGetSelectedTextCalled);
+        wrapper.setComposingRegion(0, 3);
+        assertTrue(inputConnection.isSetComposingRegionCalled);
     }
 
     private class MockInputConnection implements InputConnection {
@@ -198,12 +212,14 @@
         public boolean isGetExtractedTextCalled;
         public boolean isGetTextAfterCursorCalled;
         public boolean isGetTextBeforeCursorCalled;
+        public boolean isGetSelectedTextCalled;
         public boolean isPerformContextMenuActionCalled;
         public boolean isPerformEditorActionCalled;
         public boolean isPerformPrivateCommandCalled;
         public boolean isReportFullscreenModeCalled;
         public boolean isSendKeyEventCalled;
         public boolean isSetComposingTextCalled;
+        public boolean isSetComposingRegionCalled;
         public boolean isSetSelectionCalled;
 
         public boolean beginBatchEdit() {
@@ -261,6 +277,11 @@
             return null;
         }
 
+        public CharSequence getSelectedText(int flags) {
+            isGetSelectedTextCalled = true;
+            return null;
+        }
+
         public boolean performContextMenuAction(int id) {
             isPerformContextMenuActionCalled = true;
             return false;
@@ -291,6 +312,11 @@
             return false;
         }
 
+        public boolean setComposingRegion(int start, int end) {
+            isSetComposingRegionCalled = true;
+            return false;
+        }
+
         public boolean setSelection(int start, int end) {
             isSetSelectionCalled = true;
             return false;
diff --git a/tools/host/src/com/android/cts/Version.java b/tools/host/src/com/android/cts/Version.java
index 5f07e00..fead909 100644
--- a/tools/host/src/com/android/cts/Version.java
+++ b/tools/host/src/com/android/cts/Version.java
@@ -18,12 +18,12 @@
 
 public class Version {
     // The CTS version string
-    private static final String version = "2.2_r2";
-
+    private static final String version = "2.2_r1";
+    
     private Version() {
         // no instances allowed
     }
-
+    
     public static String asString() {
         return version;
     }
diff --git a/tools/tradefed-host/.classpath b/tools/tradefed-host/.classpath
new file mode 100644
index 0000000..67d42b5
--- /dev/null
+++ b/tools/tradefed-host/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/tradefed-prebuilt"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/ddmlib-prebuilt"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/tradefed-host/.project b/tools/tradefed-host/.project
new file mode 100644
index 0000000..990c63e
--- /dev/null
+++ b/tools/tradefed-host/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>cts-tradefed-host</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
new file mode 100644
index 0000000..a05ed40
--- /dev/null
+++ b/tools/tradefed-host/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-tradefed
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildHelper.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildHelper.java
new file mode 100644
index 0000000..d8aabc5
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tradefed.targetsetup;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Helper class for retrieving files from the CTS install.
+ * <p/>
+ * Encapsulates the filesystem layout of the CTS installation.
+ */
+public class CtsBuildHelper {
+
+    static final String CTS_DIR_NAME = "android-cts";
+    /** The root location of the extracted CTS package */
+    private final File mRootDir;
+    /** the {@link CTS_DIR_NAME} directory */
+    private final File mCtsDir;
+
+    /**
+     * Creates a {@link CtsBuildHelper}.
+     *
+     * @param rootDir the parent folder that contains the "android-cts" directory and all its
+     *            contents.
+     * @throws FileNotFoundException if file does not exist
+     */
+    public CtsBuildHelper(File rootDir) throws FileNotFoundException {
+        mRootDir = rootDir;
+        mCtsDir = new File(mRootDir, CTS_DIR_NAME);
+        if (!mCtsDir.exists()) {
+            throw new FileNotFoundException(String.format(
+                    "CTS install folder %s does not exist", mCtsDir.getAbsolutePath()));
+        }
+    }
+
+    /**
+     * @return a {@link File} representing the parent folder of the CTS installation
+     */
+    public File getRootDir() {
+        return mRootDir;
+    }
+
+    /**
+     * @return a {@link File} representing the "android-cts" folder of the CTS installation
+     */
+    public File getCtsDir() {
+        return mCtsDir;
+    }
+
+    /**
+     * @return a {@link File} representing the test application file with given name
+     * @throws FileNotFoundException if file does not exist
+     */
+    public File getTestApp(String appFileName) throws FileNotFoundException {
+        File apkFile = new File(new File(getRepositoryDir(), "testcases"), appFileName);
+        if (!apkFile.exists()) {
+            throw new FileNotFoundException(String.format("CTS test app file %s does not exist",
+                    apkFile.getAbsolutePath()));
+        }
+        return apkFile;
+    }
+
+    private File getRepositoryDir() {
+        return new File(getCtsDir(), "repository");
+    }
+
+    /**
+     * @return a {@link File} representing the test plan file with given name
+     * @throws FileNotFoundException if file does not exist
+     */
+    public File getTestPlan(String testPlanFileName) throws FileNotFoundException {
+        File planFile = new File(new File(getRepositoryDir(), "plans"), testPlanFileName);
+        if (!planFile.exists()) {
+            throw new FileNotFoundException(String.format("CTS test plan file %s does not exist",
+                    planFile.getAbsolutePath()));
+        }
+        return planFile;
+    }
+
+    /**
+     * @return a {@link File} representing the results directory.
+     */
+    public File getResultsDir() {
+        return new File(getRepositoryDir(), "results");
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildProvider.java
new file mode 100644
index 0000000..90fb8ba
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsBuildProvider.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.targetsetup;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.targetsetup.FolderBuildInfo;
+import com.android.tradefed.targetsetup.IBuildInfo;
+import com.android.tradefed.targetsetup.IBuildProvider;
+import com.android.tradefed.targetsetup.IFolderBuildInfo;
+import com.android.tradefed.targetsetup.TargetSetupError;
+
+import java.io.File;
+
+/**
+ * A simple {@link IBuildProvider} that uses a pre-existing CTS install.
+ */
+public class CtsBuildProvider implements IBuildProvider {
+
+    @Option(name="cts-install-path", description="the path to the cts installation to use")
+    private File mCtsRootDir;
+
+    /**
+     * {@inheritDoc}
+     */
+    public IBuildInfo getBuild() throws TargetSetupError {
+        if (mCtsRootDir == null) {
+            throw new IllegalArgumentException("Missing --cts-install-path");
+        }
+        IFolderBuildInfo ctsBuild = new FolderBuildInfo(0, "cts", "cts");
+        ctsBuild.setRootDir(mCtsRootDir);
+        return ctsBuild;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void buildNotTested(IBuildInfo info) {
+        // ignore
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsDeviceSetup.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsDeviceSetup.java
new file mode 100644
index 0000000..65f09f3
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsDeviceSetup.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.targetsetup;
+
+import com.android.ddmlib.Log;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetsetup.BuildError;
+import com.android.tradefed.targetsetup.DeviceSetup;
+import com.android.tradefed.targetsetup.IBuildInfo;
+import com.android.tradefed.targetsetup.IDeviceBuildInfo;
+import com.android.tradefed.targetsetup.IFolderBuildInfo;
+import com.android.tradefed.targetsetup.ITargetPreparer;
+import com.android.tradefed.targetsetup.TargetSetupError;
+
+import java.io.FileNotFoundException;
+
+/**
+ * A {@link ITargetPreparer} that accepts a device and a CTS build (represented as a
+ * {@link IDeviceBuildInfo} and a {@link IFolderBuildInfo} respectively.
+ * <p/>
+ * This class is NOT intended for 'official' CTS runs against a production device as the steps
+ * performed by this class require a debug build (aka 'adb root' must succeed).
+ */
+public class CtsDeviceSetup extends DeviceSetup {
+
+    private static final String LOG_TAG = "CtsDeviceSetup";
+
+    // TODO: read this from a configuration file rather than hard-coding
+    private static final String ACCESSIBILITY_SERVICE_APK_FILE_NAME =
+        "CtsDelegatingAccessibilityService.apk";
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            DeviceNotAvailableException, BuildError {
+        // call super class to setup device. This will disable screen guard, etc
+        super.setUp(device, buildInfo);
+
+        if (!(buildInfo instanceof IFolderBuildInfo)) {
+            throw new IllegalArgumentException("Provided buildInfo is not a IFolderBuildInfo");
+        }
+        Log.i(LOG_TAG, String.format("Setting up %s to run CTS tests", device.getSerialNumber()));
+
+        IFolderBuildInfo ctsBuild = (IFolderBuildInfo)buildInfo;
+        try {
+            CtsBuildHelper buildHelper = new CtsBuildHelper(ctsBuild.getRootDir());
+
+            // perform CTS setup steps that only work if adb is root
+
+            // TODO: turn on mock locations
+            CtsSetup ctsSetup = new CtsSetup();
+            enableAccessibilityService(device, buildHelper, ctsSetup);
+
+            // end root setup steps
+
+            // perform CTS setup common with production builds
+            ctsSetup.setUp(device, buildInfo);
+        } catch (FileNotFoundException e) {
+            throw new TargetSetupError("Invalid CTS installation", e);
+        }
+    }
+
+    private void enableAccessibilityService(ITestDevice device, CtsBuildHelper ctsBuild,
+            CtsSetup ctsSetup) throws DeviceNotAvailableException, TargetSetupError,
+            FileNotFoundException {
+        ctsSetup.installApk(device, ctsBuild.getTestApp(ACCESSIBILITY_SERVICE_APK_FILE_NAME));
+        // TODO: enable Settings > Accessibility > Accessibility > Delegating Accessibility
+        // Service
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsSetup.java b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsSetup.java
new file mode 100644
index 0000000..7af703b
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/targetsetup/CtsSetup.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.targetsetup;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetsetup.BuildError;
+import com.android.tradefed.targetsetup.IBuildInfo;
+import com.android.tradefed.targetsetup.IFolderBuildInfo;
+import com.android.tradefed.targetsetup.ITargetPreparer;
+import com.android.tradefed.targetsetup.TargetSetupError;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * A {@link ITargetPreparer} that sets up a device for CTS testing.
+ * <p/>
+ * All the actions performed in this class must work on a production device.
+ */
+public class CtsSetup implements ITargetPreparer {
+
+    private static final String RUNNER_APK_NAME = "android.core.tests.runner.apk";
+    // TODO: read this from configuration file rather than hardcoding
+    private static final String TEST_STUBS_APK = "CtsTestStubs.apk";
+
+    /**
+     * Factory method to create a {@link CtsBuildHelper}.
+     * <p/>
+     * Exposed for unit testing.
+     */
+    CtsBuildHelper createBuildHelper(File rootDir) throws FileNotFoundException {
+        return new CtsBuildHelper(rootDir);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
+            BuildError, DeviceNotAvailableException {
+        if (!(buildInfo instanceof IFolderBuildInfo)) {
+            throw new IllegalArgumentException("Provided buildInfo is not a IFolderBuildInfo");
+        }
+        IFolderBuildInfo ctsBuildInfo = (IFolderBuildInfo)buildInfo;
+        try {
+            CtsBuildHelper buildHelper = createBuildHelper(ctsBuildInfo.getRootDir());
+            installCtsPrereqs(device, buildHelper);
+            gatherDeviceStats(device, buildHelper);
+        } catch (FileNotFoundException e) {
+            throw new TargetSetupError("Invalid CTS installation", e);
+        }
+    }
+
+    /**
+     * Installs an apkFile on device.
+     *
+     * @param device the {@link ITestDevice}
+     * @param apkFile the apk {@link File}
+     * @throws DeviceNotAvailableException
+     * @throws TargetSetupError if apk cannot be installed successfully
+     */
+    void installApk(ITestDevice device, File apkFile)
+            throws DeviceNotAvailableException, TargetSetupError {
+        String errorCode = device.installPackage(apkFile, true);
+        if (errorCode != null) {
+            // TODO: retry ?
+            throw new TargetSetupError(String.format(
+                    "Failed to install %s on device %s. Reason: %s", apkFile.getName(),
+                    device.getSerialNumber(), errorCode));
+        }
+    }
+
+    /**
+     * Install pre-requisite apks for running tests
+     *
+     * @throws TargetSetupError if the pre-requisite apks fail to install
+     * @throws DeviceNotAvailableException
+     * @throws FileNotFoundException
+     */
+    private void installCtsPrereqs(ITestDevice device, CtsBuildHelper ctsBuild)
+            throws DeviceNotAvailableException, TargetSetupError, FileNotFoundException {
+        installApk(device, ctsBuild.getTestApp(TEST_STUBS_APK));
+        installApk(device, ctsBuild.getTestApp(RUNNER_APK_NAME));
+    }
+
+    private void gatherDeviceStats(ITestDevice device, CtsBuildHelper ctsBuild) {
+        // TODO: implement this
+        // install TestDeviceSetup.apk, run its instrumentation, parse results, store them in the
+        // CtsBuildInfo, then uninstall TestDeviceSetup.apk
+    }
+}
diff --git a/tools/tradefed-host/tests/.classpath b/tools/tradefed-host/tests/.classpath
new file mode 100644
index 0000000..d14e02b
--- /dev/null
+++ b/tools/tradefed-host/tests/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/cts-tradefed-host"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/easymock"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/ddmlib-prebuilt"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/tradefed-prebuilt"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/tradefed-host/tests/.project b/tools/tradefed-host/tests/.project
new file mode 100644
index 0000000..1c385d8
--- /dev/null
+++ b/tools/tradefed-host/tests/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>cts-tradefed-host-tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/tools/tradefed-host/tests/Android.mk b/tools/tradefed-host/tests/Android.mk
new file mode 100644
index 0000000..d3b94cd
--- /dev/null
+++ b/tools/tradefed-host/tests/Android.mk
@@ -0,0 +1,29 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-tradefed-tests
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt cts-tradefed
+LOCAL_STATIC_JAVA_LIBRARIES := easymock
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/CtsSetupTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/CtsSetupTest.java
new file mode 100644
index 0000000..932f3dc
--- /dev/null
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/CtsSetupTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.targetsetup;
+
+import com.android.ddmlib.Log;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.targetsetup.BuildError;
+import com.android.tradefed.targetsetup.IBuildInfo;
+import com.android.tradefed.targetsetup.IFolderBuildInfo;
+import com.android.tradefed.targetsetup.TargetSetupError;
+
+import org.easymock.EasyMock;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link CtsSetup}.
+ */
+public class CtsSetupTest extends TestCase {
+
+    private static final String LOG_TAG = "CtsSetupTest";
+
+    private CtsSetup mSetup;
+    private ITestDevice mMockDevice;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSetup = new CtsSetup() {
+            @Override
+            CtsBuildHelper createBuildHelper(File rootDir) {
+                try {
+                    return StubCtsBuildHelper.createStubHelper();
+                } catch (IOException e) {
+                    Log.e(LOG_TAG, e);
+                    fail("failed to create stub helper");
+                    return null;
+                }
+            }
+        };
+        mMockDevice = EasyMock.createMock(ITestDevice.class);
+    }
+
+    /**
+     * Test {@link CtsSetup#setUp(ITestDevice, IBuildInfo)} when provided buildInfo is the incorrect
+     * type
+     */
+    public void testSetUp_wrongBuildInfo() throws TargetSetupError, BuildError,
+            DeviceNotAvailableException {
+        try {
+            mSetup.setUp(mMockDevice, EasyMock.createMock(IBuildInfo.class));
+            fail("IllegalArgumentException not thrown");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Test normal case for {@link CtsSetup#setUp(ITestDevice, IBuildInfo)}
+     */
+    public void testSetUp() throws TargetSetupError, BuildError, DeviceNotAvailableException {
+        IFolderBuildInfo ctsBuild = EasyMock.createMock(IFolderBuildInfo.class);
+        EasyMock.expect(ctsBuild.getRootDir()).andReturn(
+                new File("tmp")).anyTimes();
+        EasyMock.expect(ctsBuild.getBuildId()).andStubReturn(0);
+        EasyMock.expect(
+                mMockDevice.installPackage((File)EasyMock.anyObject(), EasyMock.anyBoolean()))
+                .andReturn(null)
+                .anyTimes();
+        EasyMock.replay(ctsBuild, mMockDevice);
+        mSetup.setUp(mMockDevice, ctsBuild);
+    }
+}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/StubCtsBuildHelper.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/StubCtsBuildHelper.java
new file mode 100644
index 0000000..f17bd5a
--- /dev/null
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/targetsetup/StubCtsBuildHelper.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.targetsetup;
+
+import com.android.tradefed.util.FileUtil;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Stub implementation of CtsBuildHelper that returns empty files for all methods
+ */
+public class StubCtsBuildHelper extends CtsBuildHelper {
+
+    public static StubCtsBuildHelper createStubHelper() throws IOException {
+        File tmpFolder= FileUtil.createTempDir("ctstmp");
+        File ctsinstall = new File(tmpFolder, CtsBuildHelper.CTS_DIR_NAME);
+        ctsinstall.mkdirs();
+        return new StubCtsBuildHelper(tmpFolder);
+    }
+
+    private StubCtsBuildHelper(File rootDir) throws FileNotFoundException {
+        super(rootDir);
+    }
+
+    @Override
+    public File getTestApp(String appFileName) throws FileNotFoundException {
+        return new File("tmp");
+    }
+
+    @Override
+    public File getTestPlan(String testPlanFileName) throws FileNotFoundException {
+        return new File("tmp");
+    }
+}
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index b1a6700..35a3a11 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -94,9 +94,9 @@
     source_path = [
         'frameworks/base/core/java',            # android test classes
         'frameworks/base/test-runner/src',      # test runner
-        'dalvik/libcore/junit/src/main/java',   # junit classes
+        'libcore/junit/src/main/java',          # junit classes
         'development/tools/hosttestlib/src',    # hosttestlib TestCase extensions
-        'dalvik/libcore/dalvik/src/main/java',  # test annotations
+        'libcore/dalvik/src/main/java',         # test annotations
         'cts/tests/src',                        # cts test stubs
         source_root                             # the source for this package
     ]