am fb0c02e7: (-s ours) am c74cd309: am 52c31d04: (-s ours) am 7bc0e8e2: (-s ours) DO NOT MERGE Cts Feature/Profile Annotations

Merge commit 'fb0c02e7271b3eb945e353dbcf83edf173a9b40d'

* commit 'fb0c02e7271b3eb945e353dbcf83edf173a9b40d':
  DO NOT MERGE Cts Feature/Profile Annotations
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index 4c717c1..3730f85 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -20,31 +20,4 @@
     <!-- String title of the mock accessibility service -->
     <string name="title_delegating_accessibility_service">Delegating Accessibility Service</string>
 
-    <!-- String title of the accessibility end-to-end test activity -->
-    <string name="accessibility_end_to_end_test_activity">End-to-end test</string>
-
-    <!-- String value of used as text input -->
-    <string name="text_input_blah">Blah</string>
-
-    <!-- String value of used as text input -->
-    <string name="text_input_blah_blah">Blah blah</string>
-
-    <!-- String title of the button -->
-    <string name="button_title">Click me</string>
-
-    <!-- String value of the first list item -->
-    <string name="first_list_item">First list item</string>
-
-    <!-- String value of the second list item -->
-    <string name="second_list_item">Second list item</string>
-
-    <!-- String alert title -->
-    <string name="alert_title">Alert title</string>
-
-    <!-- String alert message -->
-    <string name="alert_message">Alert message</string>
-
-    <!-- String notification message -->
-    <string name="notification_message">Notification message</string>
-
 </resources>
diff --git a/tests/core/luni-io/Android.mk b/tests/core/luni-io/Android.mk
index ed39e03..6669c6a 100644
--- a/tests/core/luni-io/Android.mk
+++ b/tests/core/luni-io/Android.mk
@@ -24,7 +24,7 @@
 include $(CLEAR_VARS)
 
 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/luni/src/test/java/libcore/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) \
diff --git a/tests/res/drawable/mipmapdrawable.xml b/tests/res/drawable/mipmapdrawable.xml
new file mode 100644
index 0000000..fc6342c
--- /dev/null
+++ b/tests/res/drawable/mipmapdrawable.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<mipmap xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/testimage"/>
+    <item android:drawable="@drawable/start"/>
+</mipmap>
+
diff --git a/tests/res/xml/mipmap_correct.xml b/tests/res/xml/mipmap_correct.xml
new file mode 100644
index 0000000..46cc360
--- /dev/null
+++ b/tests/res/xml/mipmap_correct.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+
+<mipmap xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:drawable="@drawable/testimage" />
+    <item>
+        <color android:color="#77ffffff" />
+    </item>
+    <item android:drawable="@drawable/start" />
+</mipmap>
+
diff --git a/tests/res/xml/mipmap_missing_item_drawable.xml b/tests/res/xml/mipmap_missing_item_drawable.xml
new file mode 100644
index 0000000..4ef6ec7
--- /dev/null
+++ b/tests/res/xml/mipmap_missing_item_drawable.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+
+<mipmap xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item/>
+</mipmap>
+
diff --git a/tests/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java b/tests/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java
new file mode 100644
index 0000000..d1cb1ef
--- /dev/null
+++ b/tests/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import android.content.SearchRecentSuggestionsProvider;
+
+public class TestSearchRecentSuggestionsProvider extends SearchRecentSuggestionsProvider {
+    final static String AUTHORITY = "android.provider.cts.TestSRSProvider";
+    final static int MODE = DATABASE_MODE_QUERIES + DATABASE_MODE_2LINES;
+
+    public TestSearchRecentSuggestionsProvider() {
+        super();
+        setupSuggestions(AUTHORITY, MODE);
+    }
+}
diff --git a/tests/tests/accessibilityservice/AndroidManifest.xml b/tests/tests/accessibilityservice/AndroidManifest.xml
index 811c87f..b4fe6ab 100644
--- a/tests/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/tests/accessibilityservice/AndroidManifest.xml
@@ -24,7 +24,7 @@
       <uses-library android:name="android.test.runner"/>
 
       <activity android:label="@string/accessibility_end_to_end_test_activity"
-                android:name="android.accessibilityservice.cts.AccessibilityEndToEndTestActivity"/>
+              android:name="android.accessibilityservice.cts.AccessibilityEndToEndTestActivity"/>
 
   </application>
 
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index 5259753..7f5be31 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -16,6 +16,8 @@
 
 package android.accessibilityservice.cts;
 
+import com.android.cts.accessibilityservice.R;
+
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.IAccessibilityServiceDelegate;
 import android.accessibilityservice.IAccessibilityServiceDelegateConnection;
@@ -47,8 +49,6 @@
 import android.widget.EditText;
 import android.widget.ListView;
 
-import com.android.cts.accessibilityservice.R;
-
 import junit.framework.TestCase;
 
 import java.util.Iterator;
@@ -56,23 +56,25 @@
 import java.util.List;
 import java.util.Queue;
 
+import junit.framework.TestCase;
+
 /**
  * This class performs end-to-end testing of the accessibility feature by
  * creating an {@link Activity} and poking around so {@link AccessibilityEvent}s
  * are generated and their correct dispatch verified.
- * </p>
- * Note: The end-to-end test is composed of two APKs, one with a delegating accessibility
+ * <p>
+ * Note: The end-to-end test is composed of two APKs, one with a mock accessibility
  * service, another with the instrumented activity and test cases. The motivation for
  * two APKs design is that CTS tests cannot access the secure settings which is
  * required for enabling accessibility and accessibility services. Therefore, manual
- * installation of the <strong>CtsDelegatingAccessibilityService.apk</strong>
- * whose source is located at <strong>cts/tests/accessibilityservice</strong> is required.
+ * installation of the <strong>CtsAccessibilityServiceTestMockService.apk</strong>
+ * whose source is located at <strong>cts/tests/accessibility</strong> is required.
  * Once the former package has been installed accessibility must be enabled (Settings ->
- * Accessibility), the delegating service must be enabled (Settings -> Accessibility
- * -> Delegating Accessibility Service), and then the CTS tests in this package can be
- * successfully run. Further, the delegate and tests run in separate processes since
+ * Accessibility), the mock service must be enabled (Settings -> Accessibility
+ * -> Mock Accessibility Service), and then the CTS tests in this package can be
+ * successfully run. Further, the mock and tests run in separate processes since
  * the instrumentation restarts the process in which it is running and this
- * breaks the binding between the delegating accessibility service and the system.
+ * breaks the binding between the mock accessibility service and the system.
  */
 public class AccessibilityEndToEndTest extends
         ActivityInstrumentationTestCase2<AccessibilityEndToEndTestActivity> {
@@ -114,15 +116,17 @@
      * @throws Exception If any error occurs.
      */
     public AccessibilityEndToEndTest() throws Exception {
-        super("com.android.cts.accessibilityservice", AccessibilityEndToEndTestActivity.class);
+        super(AccessibilityEndToEndTestActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        // wait for the activity to settle down so we do not receive
-        // the event for its start, thus breaking the tests
-        getInstrumentation().waitForIdleSync();
+        // TODO (svetoslavganov): This is a temporary workaround for
+        // nondeterministically failing tests with partially populated events.
+        // It seems that not all times the View hierarchy is fully
+        // instantiated on time. This seems related to bug 2630683.
+        Thread.sleep(500);
     }
 
     @LargeTest
@@ -247,7 +251,7 @@
 
     @LargeTest
     public void testTypeViewTextChangedAccessibilityEvent() throws Throwable {
-        Activity activity = getActivity();
+        final Activity activity = getActivity();
 
         // focus the edit text
         final EditText editText = (EditText) activity.findViewById(R.id.edittext);
@@ -677,8 +681,7 @@
                     receivedEvent.isFullScreen());
             TestCase.assertEquals("itemCount has incorrect value", expectedEvent.getItemCount(),
                     receivedEvent.getItemCount());
-            // This will fail due to a bug fixed in Gingerbread. Bug 2593810 (removed the method).
-            // assertEqualsNotificationAsParcelableData(expectedEvent, receivedEvent);
+            assertEqualsNotificationAsParcelableData(expectedEvent, receivedEvent);
             TestCase.assertEquals("password has incorrect value", expectedEvent.isPassword(),
                     receivedEvent.isPassword());
             TestCase.assertEquals("removedCount has incorrect value", expectedEvent
@@ -687,6 +690,30 @@
         }
 
         /**
+         * Compares the {@link android.os.Parcelable} data of the
+         * <code>expectedEvent</code> and <code>receivedEvent</code> to verify
+         * that the received event is the one that is expected.
+         */
+        private void assertEqualsNotificationAsParcelableData(AccessibilityEvent expectedEvent,
+                AccessibilityEvent receivedEvent) {
+            String message = "parcelableData has incorrect value";
+            Notification expectedNotification = (Notification) expectedEvent.getParcelableData();
+            Notification receivedNotification = (Notification) receivedEvent.getParcelableData();
+
+            if (expectedNotification == null) {
+                if (receivedNotification == null) {
+                    return;
+                }
+            }
+
+            TestCase.assertNotNull(message, receivedNotification);
+
+            // we do a very simple sanity check
+            TestCase.assertEquals(message, expectedNotification.tickerText.toString(),
+                    receivedNotification.tickerText.toString());
+        }
+
+        /**
          * Compares the text of the <code>expectedEvent</code> and
          * <code>receivedEvent</code> by comparing the string representation of
          * the corresponding {@link CharSequence}s.
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTestActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTestActivity.java
index e806622..adfc9e6 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTestActivity.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTestActivity.java
@@ -16,6 +16,8 @@
 
 package android.accessibilityservice.cts;
 
+import com.android.cts.accessibilityservice.R;
+
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
@@ -26,8 +28,6 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.cts.accessibilityservice.R;
-
 /**
  * This class is an {@link Activity} used to perform end-to-end
  * testing of the accessibility feature by interaction with the
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index 48b4aae..ab7ecd7 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -72,8 +72,7 @@
                 receivedInfo.eventTypes);
         assertEquals("feedbackType not marshalled properly", sentInfo.feedbackType,
                 receivedInfo.feedbackType);
-        // This will fail here and is fixed in Froyo. Bug 2448479.
-        // assertEquals("flags not marshalled properly", sentInfo.flags, receivedInfo.flags);
+        assertEquals("flags not marshalled properly", sentInfo.flags, receivedInfo.flags);
         assertEquals("notificationTimeout not marshalled properly", sentInfo.notificationTimeout,
                 receivedInfo.notificationTimeout);
         assertEquals("packageNames not marshalled properly", sentInfo.packageNames.length,
diff --git a/tests/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
index 1861ae2..ab9e991 100644
--- a/tests/tests/app/src/android/app/cts/InstrumentationTest.java
+++ b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -960,6 +960,10 @@
             }
             
             @Override
+            public void invalidatePanelMenu(int featureId) {
+            }
+            
+            @Override
             public void takeSurface(SurfaceHolder.Callback2 callback) {
             }
             
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 0824e84..eabd470 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -394,6 +394,15 @@
             public Bundle call(String method, String request, Bundle args) {
                 return null;
             }
+            
+            public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
+                return null;
+            }
+
+            public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts)
+                    throws RemoteException, FileNotFoundException {
+                return null;
+            }
         };
         assertNull(ContentProvider.coerceToLocalContentProvider(iContentProvider));
     }
diff --git a/tests/tests/database/src/android/database/cts/AbstractCursorTest.java b/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
index 47c52ba..8f5fead 100644
--- a/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
+++ b/tests/tests/database/src/android/database/cts/AbstractCursorTest.java
@@ -453,16 +453,9 @@
         method = "getUpdatedField",
         args = {int.class}
     )
-    @ToBeFixed(bug = "1569265", explanation = "All other updating-related methods are 'hide' and "
-        + "'deprecated.")
     public void testGetUpdatedField() {
         mTestAbstractCursor.moveToFirst();
-        try {
-            assertEquals("hello", mTestAbstractCursor.getUpdatedField(0));
-            fail("getUpdatedField should throws a NullPointerException here.");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        assertNull(mTestAbstractCursor.getUpdatedField(0));
     }
 
     @TestTargetNew(
@@ -746,12 +739,6 @@
             return mRows.length;
         }
 
-        @Deprecated
-        @Override
-        public boolean deleteRow() {
-            return false;
-        }
-
         @Override
         public String[] getColumnNames() {
             return mColumnNames;
diff --git a/tests/tests/database/src/android/database/cts/CursorWrapperTest.java b/tests/tests/database/src/android/database/cts/CursorWrapperTest.java
index dba9784..df90237 100644
--- a/tests/tests/database/src/android/database/cts/CursorWrapperTest.java
+++ b/tests/tests/database/src/android/database/cts/CursorWrapperTest.java
@@ -750,7 +750,17 @@
 
     private void setupDatabase() {
         File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
-        mDatabaseFile = new File(dbDir, "database_test.db");
+        /* don't use the same database name as the one in super class
+         * this class's setUp() method deletes a database file just opened by super.setUp().
+         * that can cause corruption in database in the following situation:
+         *    super.setUp() creates the database, inserts some data into it.
+         *    this class setUp() deletes just the database file but not the associated
+         *    database files such as wal, shm files.
+         * solution is to have this class delete the whole database directory.
+         * better yet, this class shouldn't extend DatabaseCursortest at all.
+         * TODO: fix this bogus cts class hierarchy
+         */
+        mDatabaseFile = new File(dbDir, "cursor_test.db");
         if (mDatabaseFile.exists()) {
             mDatabaseFile.delete();
         }
diff --git a/tests/tests/database/src/android/database/cts/DatabaseCursorTest.java b/tests/tests/database/src/android/database/cts/DatabaseCursorTest.java
index f60638a..da9710c 100644
--- a/tests/tests/database/src/android/database/cts/DatabaseCursorTest.java
+++ b/tests/tests/database/src/android/database/cts/DatabaseCursorTest.java
@@ -107,43 +107,6 @@
     }
 
     @MediumTest
-    public void testCursorUpdate() {
-        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, d INTEGER, s INTEGER);");
-        for (int i = 0; i < 20; i++) {
-            mDatabase.execSQL("INSERT INTO test (d, s) VALUES (" + i + "," + i % 2 + ");");
-        }
-
-        Cursor testCursor = getTestCursor(mDatabase.query("test", null, "s = 0", null, null, null,
-                null));
-
-        int dCol = testCursor.getColumnIndexOrThrow("d");
-        int sCol = testCursor.getColumnIndexOrThrow("s");
-
-        int count = 0;
-        while (testCursor.moveToNext()) {
-            assertTrue(testCursor.updateInt(dCol, 3));
-            count++;
-        }
-        assertEquals(10, count);
-
-        assertTrue(testCursor.commitUpdates());
-
-        assertTrue(testCursor.requery());
-
-        count = 0;
-        while (testCursor.moveToNext()) {
-            assertEquals(3, testCursor.getInt(dCol));
-            count++;
-        }
-
-        assertEquals(10, count);
-        assertTrue(testCursor.moveToFirst());
-        assertTrue(testCursor.deleteRow());
-        assertEquals(9, testCursor.getCount());
-        testCursor.close();
-    }
-
-    @MediumTest
     public void testBlob() throws Exception {
         // create table
         mDatabase.execSQL(
@@ -182,23 +145,6 @@
         assertEquals(s, testCursor.getString(sCol));
         assertEquals((double) d, testCursor.getDouble(dCol));
         assertEquals((long) l, testCursor.getLong(lCol));
-
-        // new byte[]
-        byte[] newblob = new byte[1000];
-        value = 98;
-        Arrays.fill(blob, value);
-
-        testCursor.updateBlob(bCol, newblob);
-        cBlob = testCursor.getBlob(bCol);
-        assertTrue(Arrays.equals(newblob, cBlob));
-
-        // commit
-        assertTrue(testCursor.commitUpdates());
-        assertTrue(testCursor.requery());
-        testCursor.moveToNext();
-        cBlob = testCursor.getBlob(bCol);
-        assertTrue(Arrays.equals(newblob, cBlob));
-        testCursor.close();
     }
 
     @MediumTest
diff --git a/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
index c47b65b..ae2a204 100644
--- a/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
+++ b/tests/tests/database/src/android/database/cts/DatabaseUtilsTest.java
@@ -33,11 +33,15 @@
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteStatement;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintStream;
 
 @TestTargetClass(android.database.DatabaseUtils.class)
@@ -64,6 +68,8 @@
         assertNotNull(mDatabase);
         mDatabase.execSQL("CREATE TABLE " + TABLE_NAME + " (_id INTEGER PRIMARY KEY, " +
                 "name TEXT, age INTEGER, address TEXT);");
+        mDatabase.execSQL(
+                "CREATE TABLE blob_test (_id INTEGER PRIMARY KEY, name TEXT, data BLOB)");
     }
 
     @Override
@@ -769,11 +775,98 @@
 
         args = new String[] { "1000" }; // NO people can be older than this.
         try {
-            DatabaseUtils.stringForQuery(statement, args);
+            DatabaseUtils.blobFileDescriptorForQuery(statement, args);
             fail("should throw SQLiteDoneException");
         } catch (SQLiteDoneException e) {
             // expected
         }
         statement.close();
     }
-}
\ No newline at end of file
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "blobFileDescriptorForQuery",
+            args = {android.database.sqlite.SQLiteDatabase.class, java.lang.String.class,
+                    java.lang.String[].class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "blobFileDescriptorForQuery",
+            args = {android.database.sqlite.SQLiteStatement.class, java.lang.String[].class}
+        )
+    })
+    public void testBlobFileDescriptorForQuery() throws Exception {
+        String data1 = "5300FEFF";
+        String data2 = "DECAFBAD";
+        mDatabase.execSQL("INSERT INTO blob_test (name, data) VALUES ('Mike', X'" + data1 + "')");
+
+        String query = "SELECT data FROM blob_test";
+        assertFileDescriptorContent(parseBlob(data1),
+                        DatabaseUtils.blobFileDescriptorForQuery(mDatabase, query, null));
+
+        mDatabase.execSQL("INSERT INTO blob_test (name, data) VALUES ('Jack', X'" + data2 + "');");
+        query = "SELECT data FROM blob_test WHERE name = ?";
+        String[] args = new String[] { "Jack" };
+        assertFileDescriptorContent(parseBlob(data2),
+                DatabaseUtils.blobFileDescriptorForQuery(mDatabase, query, args));
+
+        args = new String[] { "No such name" };
+        try {
+            DatabaseUtils.stringForQuery(mDatabase, query, args);
+            fail("should throw SQLiteDoneException");
+        } catch (SQLiteDoneException e) {
+            // expected
+        }
+
+        query = "SELECT data FROM blob_test WHERE name = ?;";
+        SQLiteStatement statement = mDatabase.compileStatement(query);
+        args = new String[] { "Mike" };
+        assertFileDescriptorContent(parseBlob(data1),
+                DatabaseUtils.blobFileDescriptorForQuery(statement, args));
+
+        args = new String[] { "No such name" };
+        try {
+            DatabaseUtils.blobFileDescriptorForQuery(statement, args);
+            fail("should throw SQLiteDoneException");
+        } catch (SQLiteDoneException e) {
+            // expected
+        }
+        statement.close();
+    }
+
+    private static byte[] parseBlob(String src) {
+        int len = src.length();
+        byte[] result = new byte[len / 2];
+
+        for (int i = 0; i < len/2; i++) {
+            int val;
+            char c1 = src.charAt(i*2);
+            char c2 = src.charAt(i*2+1);
+            int val1 = Character.digit(c1, 16);
+            int val2 = Character.digit(c2, 16);
+            val = (val1 << 4) | val2;
+            result[i] = (byte)val;
+        }
+        return result;
+    }
+
+    private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+            throws IOException {
+        assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+    }
+
+    private static void assertInputStreamContent(byte[] expected, InputStream is)
+            throws IOException {
+        try {
+            byte[] observed = new byte[expected.length];
+            int count = is.read(observed);
+            assertEquals(expected.length, count);
+            assertEquals(-1, is.read());
+            MoreAsserts.assertEquals(expected, observed);
+        } finally {
+            is.close();
+        }
+    }
+
+}
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java
index ae5b9d4..d608c2f 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteCursorTest.java
@@ -24,6 +24,7 @@
 
 import android.content.Context;
 import android.database.AbstractCursor;
+import android.database.Cursor;
 import android.database.CursorWindow;
 import android.database.DataSetObserver;
 import android.database.StaleDataException;
@@ -79,8 +80,8 @@
                 TEST_SQL, TABLE_NAME);
         try {
             new SQLiteCursor(mDatabase, cursorDriver, TABLE_NAME, null);
-            fail("constructor didn't throw NullPointerException when SQLiteQuery is null");
-        } catch (NullPointerException e) {
+            fail("constructor didn't throw IllegalArgumentException when SQLiteQuery is null");
+        } catch (IllegalArgumentException e) {
         }
 
         // get SQLiteCursor by querying database
@@ -221,6 +222,44 @@
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
+            method = "requery",
+            args = {}
+        )
+    })
+    public void testRequery2() {
+        mDatabase.disableWriteAheadLogging();
+        mDatabase.execSQL("create table testRequery2 (i int);");
+        mDatabase.execSQL("insert into testRequery2 values(1);");
+        mDatabase.execSQL("insert into testRequery2 values(2);");
+        Cursor c = mDatabase.rawQuery("select * from testRequery2 order by i", null);
+        assertEquals(2, c.getCount());
+        assertTrue(c.moveToFirst());
+        assertEquals(1, c.getInt(0));
+        assertTrue(c.moveToNext());
+        assertEquals(2, c.getInt(0));
+        // add more data to the table and requery
+        mDatabase.execSQL("insert into testRequery2 values(3);");
+        assertTrue(c.requery());
+        assertEquals(3, c.getCount());
+        assertTrue(c.moveToFirst());
+        assertEquals(1, c.getInt(0));
+        assertTrue(c.moveToNext());
+        assertEquals(2, c.getInt(0));
+        assertTrue(c.moveToNext());
+        assertEquals(3, c.getInt(0));
+        // close the database and see if requery throws an exception
+        mDatabase.close();
+        try {
+            c.requery();
+            fail("expected IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
             method = "getColumnIndex",
             args = {java.lang.String.class}
         ),
@@ -242,16 +281,6 @@
 
     @TestTargetNew(
         level = TestLevel.COMPLETE,
-        method = "getDatabase",
-        args = {}
-    )
-    public void testGetDatabase() {
-        SQLiteCursor cursor = getCursor();
-        assertSame(mDatabase, cursor.getDatabase());
-    }
-
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
         method = "setSelectionArguments",
         args = {java.lang.String[].class}
     )
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
index 7a18cd8..e5d5a30 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
@@ -18,10 +18,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
 
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -37,6 +34,8 @@
 import android.database.sqlite.SQLiteTransactionListener;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestLevel;
@@ -150,6 +149,7 @@
         }
 
         File dbFile = new File(mDatabaseDir, "database_test12345678.db");
+        dbFile.delete();
         assertFalse(dbFile.exists());
         db = SQLiteDatabase.openOrCreateDatabase(dbFile.getPath(), factory);
         assertNotNull(db);
@@ -338,88 +338,6 @@
         }
     }
 
-    @SuppressWarnings("deprecation")
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            notes = "Test getSyncedTables()",
-            method = "getSyncedTables",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            notes = "Test markTableSyncable(String, String)",
-            method = "markTableSyncable",
-            args = {java.lang.String.class, java.lang.String.class}
-        )
-    })
-    public void testGetSyncedTables() {
-        mDatabase.execSQL("CREATE TABLE people (_id INTEGER PRIMARY KEY, name TEXT, "
-                + "_sync_dirty INTEGER);");
-        mDatabase.execSQL("CREATE TABLE _delete_people (name TEXT);");
-        Map<String, String> tableMap = mDatabase.getSyncedTables();
-        assertEquals(0, tableMap.size());
-        mDatabase.markTableSyncable("people", "_delete_people");
-        tableMap = mDatabase.getSyncedTables();
-        assertEquals(1, tableMap.size());
-        Set<String> keys = tableMap.keySet();
-        Iterator<String> iterator = keys.iterator();
-        assertTrue(iterator.hasNext());
-        assertEquals("people", iterator.next());
-        assertEquals("_delete_people", tableMap.get("people"));
-        assertFalse(iterator.hasNext());
-
-        // test sync
-        mDatabase.execSQL("INSERT INTO people VALUES (0, \"foo\", 0);");
-        Cursor c = mDatabase.query("people", new String[] {"_id", "name" },
-                "_id = 0", null, null, null, null);
-        assertTrue(c.moveToFirst());
-        c.updateString(1, "updated");
-        c.commitUpdates();
-        c.close();
-        c = mDatabase.query("people", new String[] {"_id", "_sync_dirty" },
-                "_id = 0", null, null, null, null);
-        assertTrue(c.moveToFirst());
-        // _sync_dirty flag has been set
-        assertEquals(1, c.getInt(1));
-        c.close();
-    }
-
-    @SuppressWarnings("deprecation")
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "Test markTableSyncable(String, String, String)",
-        method = "markTableSyncable",
-        args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
-    )
-    public void testMarkTableSyncable() {
-        mDatabase.execSQL("CREATE TABLE phone (_id INTEGER PRIMARY KEY, _people_id INTEGER, " +
-                "name TEXT);");
-        mDatabase.execSQL("CREATE TABLE people (_id INTEGER PRIMARY KEY, " +
-                "name TEXT, _sync_dirty INTEGER);");
-        mDatabase.markTableSyncable("phone", "_people_id", "people");
-
-        Map<String, String> tableMap = mDatabase.getSyncedTables();
-        // since no delete table was given, there is no mapping
-        assertEquals(0, tableMap.size());
-
-        // test sync
-        mDatabase.execSQL("INSERT INTO people VALUES (13, \"foo\", 0);");
-        mDatabase.execSQL("INSERT INTO phone VALUES (0, 13, \"bar\");");
-        Cursor c = mDatabase.query("phone", new String[] {"_id", "name" },
-                "_id = 0", null, null, null, null);
-        assertTrue(c.moveToFirst());
-        c.updateString(1, "updated");
-        c.commitUpdates();
-        c.close();
-        c = mDatabase.query("people", new String[] {"_id", "_sync_dirty" },
-                "_id = 13", null, null, null, null);
-        assertTrue(c.moveToFirst());
-        // _sync_dirty flag has been set
-        assertEquals(1, c.getInt(1));
-        c.close();
-    }
-
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
@@ -546,7 +464,8 @@
         mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Jim', 35, 'Chicago');");
 
         // delete one record.
-        mDatabase.delete(TABLE_NAME, "name = 'Mike'", null);
+        int count = mDatabase.delete(TABLE_NAME, "name = 'Mike'", null);
+        assertEquals(1, count);
 
         Cursor cursor = mDatabase.query(TABLE_NAME, TEST_PROJECTION, null,
                 null, null, null, null);
@@ -564,7 +483,8 @@
         cursor.close();
 
         // delete another record.
-        mDatabase.delete(TABLE_NAME, "name = ?", new String[] { "Jack" });
+        count = mDatabase.delete(TABLE_NAME, "name = ?", new String[] { "Jack" });
+        assertEquals(1, count);
 
         cursor = mDatabase.query(TABLE_NAME, TEST_PROJECTION, null, null, null,
                 null, null);
@@ -581,7 +501,8 @@
         mDatabase.execSQL("INSERT INTO test (name, age, address) VALUES ('Jack', 30, 'London');");
 
         // delete all records.
-        mDatabase.delete(TABLE_NAME, null, null);
+        count = mDatabase.delete(TABLE_NAME, null, null);
+        assertEquals(3, count);
 
         cursor = mDatabase.query(TABLE_NAME, TEST_PROJECTION, null, null, null, null, null);
         assertNotNull(cursor);
@@ -1594,4 +1515,128 @@
         assertEquals(1, cursor.getInt(0));
         assertEquals(2, cursor.getInt(1));
     }
+
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "test enableWriteAheadLogging",
+            method = "enableWriteAheadLogging",
+            args = {}
+        )
+    /**
+     * With sqlite's write-ahead-logging (WAL) enabled, readers get old version of data
+     * from the table that a writer is modifying at the same time.
+     * <p>
+     * This method does the following to test this sqlite3 feature
+     * <ol>
+     *   <li>creates a table in the database and populates it with 5 rows of data</li>
+     *   <li>do "select count(*) from this_table" and expect to receive 5</li>
+     *   <li>start a writer thread who BEGINs a transaction, INSERTs a single row
+     *   into this_table</li>
+     *   <li>writer stops the transaction at this point, kicks off a reader thread - which will
+     *       do  the above SELECT query: "select count(*) from this_table"</li>
+     *   <li>this query should return value 5 - because writer is still in transaction and
+     *    sqlite returns OLD version of the data</li>
+     *   <li>writer ends the transaction, thus making the extra row now visible to everyone</li>
+     *   <li>reader is kicked off again to do the same query. this time query should
+     *   return value = 6 which includes the newly inserted row into this_table.</li>
+     *</p>
+     * @throws InterruptedException
+     */
+    @LargeTest
+    public void testReaderGetsOldVersionOfDataWhenWriterIsInXact() throws InterruptedException {
+        // redo setup to create WAL enabled database
+        mDatabase.close();
+        new File(mDatabase.getPath()).delete();
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null, null);
+        boolean rslt = mDatabase.enableWriteAheadLogging();
+        assertTrue(rslt);
+        assertNotNull(mDatabase);
+
+        // create a new table and insert 5 records into it.
+        mDatabase.execSQL("CREATE TABLE t1 (i int, j int);");
+        mDatabase.beginTransaction();
+        for (int i = 0; i < 5; i++) {
+            mDatabase.execSQL("insert into t1 values(?,?);", new String[] {i+"", i+""});
+        }
+        mDatabase.setTransactionSuccessful();
+        mDatabase.endTransaction();
+
+        // make sure a reader can read the above data
+        ReaderQueryingData r1 = new ReaderQueryingData(5);
+        r1.start();
+        Thread.yield();
+        try {r1.join();} catch (Exception e) {}
+
+        WriterDoingSingleTransaction w = new WriterDoingSingleTransaction();
+        w.start();
+        w.join();
+    }
+
+    private class WriterDoingSingleTransaction extends Thread {
+        @Override public void run() {
+            // start a transaction
+            mDatabase.beginTransactionNonExclusive();
+            mDatabase.execSQL("insert into t1 values(?,?);", new String[] {"11", "11"});
+            assertTrue(mDatabase.isOpen());
+
+            // while the writer is in a transaction, start a reader and make sure it can still
+            // read 5 rows of data (= old data prior to the current transaction)
+            ReaderQueryingData r1 = new ReaderQueryingData(5);
+            r1.start();
+            try {r1.join();} catch (Exception e) {}
+
+            // now, have the writer do the select count(*)
+            // it should execute on the same connection as this transaction
+            // and count(*) should reflect the newly inserted row
+            Long l = DatabaseUtils.longForQuery(mDatabase, "select count(*) from t1", null);
+            assertEquals(6, l.intValue());
+
+            // end transaction
+            mDatabase.setTransactionSuccessful();
+            mDatabase.endTransaction();
+
+            // reader should now be able to read 6 rows = new data AFTER this transaction
+            r1 = new ReaderQueryingData(6);
+            r1.start();
+            try {r1.join();} catch (Exception e) {}
+        }
+    }
+
+    private class ReaderQueryingData extends Thread {
+        private int count;
+        /**
+         * constructor with a param to indicate the number of rows expected to be read
+         */
+        public ReaderQueryingData(int count) {
+            this.count = count;
+        }
+        @Override public void run() {
+            Long l = DatabaseUtils.longForQuery(mDatabase, "select count(*) from t1", null);
+            assertEquals(count, l.intValue());
+        }
+    }
+
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "test exceptions from enableWriteAheadLogging().",
+            method = "enableWriteAheadLogging",
+            args = {}
+        )
+    public void testExceptionsFromEnableWriteAheadLogging() {
+        // attach a database
+        // redo setup to create WAL enabled database
+        mDatabase.close();
+        new File(mDatabase.getPath()).delete();
+        mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null, null);
+
+        // attach a database and call enableWriteAheadLogging - should not be allowed
+        mDatabase.execSQL("attach database ':memory:' as memoryDb");
+        boolean rslt = mDatabase.enableWriteAheadLogging();
+        assertFalse(rslt);
+        // enableWriteAheadLogging on memory database is not allowed
+        SQLiteDatabase db = SQLiteDatabase.create(null);
+        rslt = db.enableWriteAheadLogging();
+        assertFalse(rslt);
+        db.close();
+    }
 }
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteProgramTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteProgramTest.java
index 89918a1..a9a3293 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteProgramTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteProgramTest.java
@@ -20,13 +20,13 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
-import dalvik.annotation.ToBeFixed;
 
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDoneException;
 import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteQuery;
 import android.database.sqlite.SQLiteStatement;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
@@ -37,9 +37,6 @@
 
     private SQLiteDatabase mDatabase;
 
-    @ToBeFixed(bug="1448885", explanation="SQLiteProgram is an abstract class and its " +
-            "constructor is package private, so it can not be extended directly to test. " +
-            "For this reason, the test uses SQLiteStatement instead.")
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -57,79 +54,6 @@
         super.tearDown();
     }
 
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "Test getUniqueId()",
-        method = "getUniqueId",
-        args = {}
-    )
-    public void testGetUniqueId() {
-        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
-                "num1 INTEGER, num2 INTEGER, image BLOB);");
-        final String statement = "DELETE FROM test WHERE _id=?;";
-        SQLiteStatement statementOne = mDatabase.compileStatement(statement);
-        SQLiteStatement statementTwo = mDatabase.compileStatement(statement);
-        // since the same compiled statement is being accessed at the same time by 2 different
-        // objects, they each get their own statement id
-        assertTrue(statementOne.getUniqueId() != statementTwo.getUniqueId());
-        statementOne.close();
-        statementTwo.close();
-        
-        statementOne = mDatabase.compileStatement(statement);
-        int n = statementOne.getUniqueId();
-        statementOne.close();
-        statementTwo = mDatabase.compileStatement(statement);
-        assertEquals(n, statementTwo.getUniqueId());
-        statementTwo.close();
-
-        // now try to compile 2 different statements and they should have different uniquerIds.
-        SQLiteStatement statement1 = mDatabase.compileStatement("DELETE FROM test WHERE _id=1;");
-        SQLiteStatement statement2 = mDatabase.compileStatement("DELETE FROM test WHERE _id=2;");
-        assertTrue(statement1.getUniqueId() != statement2.getUniqueId());
-        statement1.close();
-        statement2.close();
-    }
-
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "Test onAllReferencesReleased(). Since sql statements are always cached in " +
-        		"SQLiteDatabase, compiledSql should NOT be released " +
-        		"when onAllReferencesReleased() is called",
-        method = "onAllReferencesReleased",
-        args = {}
-    )
-    public void testOnAllReferencesReleased() {
-        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
-                "num1 INTEGER, num2 INTEGER, image BLOB);");
-        final String statement = "DELETE FROM test WHERE _id=?;";
-        SQLiteStatement statementOne = mDatabase.compileStatement(statement);
-        assertTrue(statementOne.getUniqueId() > 0);
-        int nStatement = statementOne.getUniqueId();
-        statementOne.releaseReference();
-        assertTrue(statementOne.getUniqueId() == nStatement);
-        statementOne.close();
-    }
-
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "Test onAllReferencesReleasedFromContainer(). " +
-        		"Since sql statements are always cached in " +
-                "SQLiteDatabase, compiledSql should NOT be released " +
-                "when onAllReferencesReleasedFromContainer() is called",
-        args = {}
-    )
-    public void testOnAllReferencesReleasedFromContainer() {
-        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
-                "num1 INTEGER, num2 INTEGER, image BLOB);");
-        final String statement = "DELETE FROM test WHERE _id=?;";
-        SQLiteStatement statementOne = mDatabase.compileStatement(statement);
-        assertTrue(statementOne.getUniqueId() > 0);
-        int nStatement = statementOne.getUniqueId();
-        statementOne.releaseReferenceFromContainer();
-        assertTrue(statementOne.getUniqueId() == nStatement);
-        statementOne.close();
-    }
-
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
@@ -195,39 +119,36 @@
         }
         statement.close();
 
-        statement = mDatabase.compileStatement("SELECT text1 FROM test;");
+        Cursor cursor = null;
         try {
-            statement.bindString(1, "foo");
+            cursor = mDatabase.query("test", new String[]{"text1"}, "where text1='a'",
+                    new String[]{"foo"}, null, null, null);
             fail("Should throw exception (no value to bind)");
         } catch (SQLiteException expected) {
             // expected
-        }
-
-        statement =
-            mDatabase.compileStatement("SELECT text1 FROM test WHERE text2 = ? AND num2 = ?;");
-
-        try {
-            statement.bindString(0, "Jack");
-            fail("Should throw exception (index is 0)");
-        } catch (SQLiteException expected) {
-            // expected
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
         }
         try {
-            statement.bindLong(-1, 30);
-            fail("Should throw exception (index is negative)");
-        } catch (SQLiteException expected) {
-            // expected
-        }
-        try {
-            statement.bindDouble(3, 589.0);
+            cursor = mDatabase.query("test", new String[]{"text1"}, "where text1='a'",
+                    new String[]{"foo", "bar"}, null, null, null);
             fail("Should throw exception (index too large)");
         } catch (SQLiteException expected) {
             // expected
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
         }
         // test positive case
+        statement = mDatabase.compileStatement(
+                "SELECT text1 FROM test WHERE text2 = ? AND num2 = ?;");
         statement.bindString(1, "Jack");
         statement.bindLong(2, 30);
         assertEquals("Mike", statement.simpleQueryForString());
+        statement.close();
     }
 
     @TestTargetNew(
@@ -303,64 +224,4 @@
         MoreAsserts.assertEquals(blob, value);
         cursor.close();
     }
-
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "onAllReferencesReleased",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "onAllReferencesReleasedFromContainer",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "compile",
-            args = {java.lang.String.class, boolean.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "native_bind_blob",
-            args = {int.class, byte[].class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "native_bind_double",
-            args = {int.class, double.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "native_bind_long",
-            args = {int.class, long.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "native_bind_null",
-            args = {int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.NOT_FEASIBLE,
-            method = "native_compile",
-            args = {java.lang.String.class}
-        )
-    })
-    @ToBeFixed(bug = "1448885", explanation = "Cannot test protected methods, since constructor" +
-        " is private.")
-    public void testProtectedMethods() {
-        // cannot test
-    }
-
-    private void closeDatabaseWithOrphanedStatement(){
-        try {
-            mDatabase.close();
-        } catch (SQLiteException e) {
-            // A SQLiteException is thrown if there are some unfinialized exceptions
-            // This is expected as some tests explicitly leave statements in this state
-            if (!e.getMessage().equals("Unable to close due to unfinalised statements")) {
-                throw e;
-            }
-        }
-    }
 }
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
index ec6b79a..828045a 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteStatementTest.java
@@ -21,19 +21,35 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 
+import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.database.DatabaseUtils;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDoneException;
 import android.database.sqlite.SQLiteStatement;
+import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+
+import java.io.IOException;
+import java.io.InputStream;
 
 @TestTargetClass(android.database.sqlite.SQLiteStatement.class)
 public class SQLiteStatementTest extends AndroidTestCase {
     private static final String STRING1 = "this is a test";
     private static final String STRING2 = "another test";
 
+    private static final byte[][] BLOBS = new byte [][] {
+        parseBlob("86FADCF1A820666AEBD0789F47932151A2EF734269E8AC4E39630AB60519DFD8"),
+        new byte[0],
+        null,
+        parseBlob("00"),
+        parseBlob("FF"),
+        parseBlob("D7B500FECF25F7A4D83BF823D3858690790F2526013DE6CAE9A69170E2A1E47238"),
+    };
+
     private static final String DATABASE_NAME = "database_test.db";
 
     private static final int CURRENT_DATABASE_VERSION = 42;
@@ -60,40 +76,62 @@
         mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
     }
 
+    private void populateBlobTable() {
+        mDatabase.execSQL("CREATE TABLE blob_test (_id INTEGER PRIMARY KEY, data BLOB)");
+        for (int i = 0; i < BLOBS.length; i++) {
+            ContentValues values = new ContentValues();
+            values.put("_id", i);
+            values.put("data", BLOBS[i]);
+            mDatabase.insert("blob_test", null, values);
+        }
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
-        method = "execute",
+        method = "executeUpdateDelete",
         args = {}
     )
     public void testExecute() {
+        mDatabase.disableWriteAheadLogging();
         populateDefaultTable();
 
-        Cursor c = mDatabase.query("test", null, null, null, null, null, null);
-        assertEquals(0, c.getCount());
+        assertEquals(0, DatabaseUtils.longForQuery(mDatabase, "select count(*) from test", null));
 
-        // test insert
-        SQLiteStatement statement = mDatabase.compileStatement(
-                "INSERT INTO test (data) VALUES ('" + STRING1 + "')");
-        statement.execute();
+        // test update
+        // insert 2 rows and then update them.
+        SQLiteStatement statement1 = mDatabase.compileStatement(
+                "INSERT INTO test (data) VALUES ('" + STRING2 + "')");
+        assertEquals(1, statement1.executeInsert());
+        assertEquals(2, statement1.executeInsert());
+        SQLiteStatement statement2 =
+                mDatabase.compileStatement("UPDATE test set data = 'a' WHERE _id > 0");
+        assertEquals(2, statement2.executeUpdateDelete());
+        statement2.close();
+        // should still have 2 rows in the table
+        assertEquals(2, DatabaseUtils.longForQuery(mDatabase, "select count(*) from test", null));
 
-        c = mDatabase.query("test", null, null, null, null, null, null);
-        assertEquals(1, c.getCount());
+        // test delete
+        // insert 2 more rows and delete 3 of them
+        assertEquals(3, statement1.executeInsert());
+        assertEquals(4, statement1.executeInsert());
+        statement1.close();
+        statement2 = mDatabase.compileStatement("DELETE from test WHERE _id < 4");
+        assertEquals(3, statement2.executeUpdateDelete());
+        statement2.close();
+        // should still have 1 row1 in the table
+        assertEquals(1, DatabaseUtils.longForQuery(mDatabase, "select count(*) from test", null));
 
-        c.moveToFirst();
-        assertEquals(STRING1, c.getString(c.getColumnIndex("data")));
-
-        // invalid SQL statement
-        statement = mDatabase.compileStatement(
-                "SELECT * FROM test WHERE data=\"" + STRING1 + "\"");
+        // if the SQL statement is something that causes rows of data to
+        // be returned, executeUpdateDelete() (and execute()) throw an exception.
+        statement2 = mDatabase.compileStatement("SELECT count(*) FROM test");
         try {
-            statement.execute();
-            fail("There should be a SQLException thrown out.");
+            statement2.executeUpdateDelete();
+            fail("exception expected");
         } catch (SQLException e) {
-            // expected.
+            // expected
+        } finally {
+            statement2.close();
         }
-
-        c.deactivate();
-        statement.close();
     }
 
     @TestTargets({
@@ -118,25 +156,33 @@
         SQLiteStatement statement = mDatabase.compileStatement(
                 "INSERT INTO test (data) VALUES ('" + STRING2 + "')");
         assertEquals(1, statement.executeInsert());
+        statement.close();
+
+        // try to insert another row with the same id. last inserted rowid should be -1
+        statement = mDatabase.compileStatement("insert or ignore into test values(1, 1);");
+        assertEquals(-1, statement.executeInsert());
+        statement.close();
 
         c = mDatabase.query("test", null, null, null, null, null, null);
         assertEquals(1, c.getCount());
 
         c.moveToFirst();
         assertEquals(STRING2, c.getString(c.getColumnIndex("data")));
+        c.close();
 
-        // invalid SQL statement
+        // if the sql statement is something that causes rows of data to
+        // be returned, executeInsert() throws an exception
         statement = mDatabase.compileStatement(
                 "SELECT * FROM test WHERE data=\"" + STRING2 + "\"");
         try {
             statement.executeInsert();
-            fail("There should be a SQLException thrown out.");
+            fail("exception expected");
         } catch (SQLException e) {
-            // expected.
-        }
+            // expected
+        } finally {
+            statement.close();
 
-        c.deactivate();
-        statement.close();
+        }
     }
 
     @TestTargetNew(
@@ -196,4 +242,177 @@
 
         statement.close();
     }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessNormal() throws IOException {
+        doTestSimpleQueryForBlobFileDescriptorSuccess(0);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessEmpty() throws IOException {
+        doTestSimpleQueryForBlobFileDescriptorSuccess(1);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessNull() {
+        populateBlobTable();
+
+        String sql = "SELECT data FROM blob_test WHERE _id = " + 2;
+        SQLiteStatement stm = mDatabase.compileStatement(sql);
+        assertNull(stm.simpleQueryForBlobFileDescriptor());
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccess00() throws IOException {
+        doTestSimpleQueryForBlobFileDescriptorSuccess(3);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessFF() throws IOException {
+        doTestSimpleQueryForBlobFileDescriptorSuccess(4);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessEmbeddedNul() throws IOException {
+        doTestSimpleQueryForBlobFileDescriptorSuccess(5);
+    }
+
+    private void doTestSimpleQueryForBlobFileDescriptorSuccess(int i) throws IOException {
+        populateBlobTable();
+
+        String sql = "SELECT data FROM blob_test WHERE _id = " + i;
+        SQLiteStatement stm = mDatabase.compileStatement(sql);
+        ParcelFileDescriptor fd = stm.simpleQueryForBlobFileDescriptor();
+        assertFileDescriptorContent(BLOBS[i], fd);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testSimpleQueryForBlobFileDescriptorSuccessParam() throws IOException {
+        populateBlobTable();
+
+        String sql = "SELECT data FROM blob_test WHERE _id = ?";
+        SQLiteStatement stm = mDatabase.compileStatement(sql);
+        stm.bindLong(1, 0);
+        ParcelFileDescriptor fd = stm.simpleQueryForBlobFileDescriptor();
+        assertFileDescriptorContent(BLOBS[0], fd);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testGetBlobFailureNoParam() throws Exception {
+        populateBlobTable();
+
+        String sql = "SELECT data FROM blob_test WHERE _id = 100";
+        SQLiteStatement stm = mDatabase.compileStatement(sql);
+        ParcelFileDescriptor fd = null;
+        SQLiteDoneException expectedException = null;
+        try {
+            fd = stm.simpleQueryForBlobFileDescriptor();
+        } catch (SQLiteDoneException ex) {
+            expectedException = ex;
+        } finally {
+            if (fd != null) {
+                fd.close();
+                fd = null;
+            }
+        }
+        assertNotNull("Should have thrown SQLiteDoneException", expectedException);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        method = "simpleQueryForBlobFileDescriptor",
+        args = {}
+    )
+    public void testGetBlobFailureParam() throws Exception {
+        populateBlobTable();
+
+        String sql = "SELECT data FROM blob_test WHERE _id = ?";
+        SQLiteStatement stm = mDatabase.compileStatement(sql);
+        stm.bindLong(1, 100);
+        ParcelFileDescriptor fd = null;
+        SQLiteDoneException expectedException = null;
+        try {
+            fd = stm.simpleQueryForBlobFileDescriptor();
+        } catch (SQLiteDoneException ex) {
+            expectedException = ex;
+        } finally {
+            if (fd != null) {
+                fd.close();
+                fd = null;
+            }
+        }
+        assertNotNull("Should have thrown SQLiteDoneException", expectedException);
+    }
+
+    /*
+     * Convert string of hex digits to byte array.
+     * Results are undefined for poorly formed string.
+     *
+     * @param src hex string
+     */
+    private static byte[] parseBlob(String src) {
+        int len = src.length();
+        byte[] result = new byte[len / 2];
+
+        for (int i = 0; i < len/2; i++) {
+            int val;
+            char c1 = src.charAt(i*2);
+            char c2 = src.charAt(i*2+1);
+            int val1 = Character.digit(c1, 16);
+            int val2 = Character.digit(c2, 16);
+            val = (val1 << 4) | val2;
+            result[i] = (byte)val;
+        }
+        return result;
+    }
+
+    private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+            throws IOException {
+        assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+    }
+
+    private static void assertInputStreamContent(byte[] expected, InputStream is)
+            throws IOException {
+        try {
+            byte[] observed = new byte[expected.length];
+            int count = is.read(observed);
+            assertEquals(expected.length, count);
+            assertEquals(-1, is.read());
+            MoreAsserts.assertEquals(expected, observed);
+        } finally {
+            is.close();
+        }
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 07612d4..b00a383 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -96,7 +96,6 @@
     )
     public void testCanvas1() {
         final Canvas c = new Canvas();
-        assertNull(c.getGL());
     }
 
     @TestTargetNew(
@@ -128,36 +127,6 @@
         new Canvas(mMutableBitmap);
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "Canvas",
-            args = {javax.microedition.khronos.opengles.GL.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getGL",
-            args = {}
-        )
-    })
-    public void testCanvas3() {
-        Canvas c = new Canvas();
-        assertNull(c.getGL());
-        final MyGL myGL = new MyGL();
-        c = new Canvas(myGL);
-        assertTrue(myGL.equals(c.getGL()));
-    }
-
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        method = "freeGlCaches",
-        args = {}
-    )
-    public void testFreeGlCaches() {
-        // can't get the changed state
-        Canvas.freeGlCaches();
-    }
-
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "setBitmap",
@@ -173,16 +142,6 @@
             // expected
         }
 
-        // abnormal case: GL not null
-        final Canvas c = new Canvas(new MyGL());
-        try {
-            c.setBitmap(mMutableBitmap);
-            fail("should throw out RuntimeException when setting MutableBitmap to Canvas "
-                    + "when the Canvas is created with GL");
-        } catch (RuntimeException e) {
-            // expected
-        }
-
         // abnormal case: bitmap to be set has been recycled
         mMutableBitmap.recycle();
         try {
@@ -199,39 +158,6 @@
         assertEquals(31, mCanvas.getHeight());
     }
 
-    @TestTargets({
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "setViewport",
-            args = {int.class, int.class}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getWidth",
-            args = {}
-        ),
-        @TestTargetNew(
-            level = TestLevel.COMPLETE,
-            method = "getHeight",
-            args = {}
-        )
-    })
-    public void testSetViewport() {
-        assertEquals(BITMAP_WIDTH, mCanvas.getWidth());
-        assertEquals(BITMAP_HEIGHT, mCanvas.getHeight());
-
-        // set viewport has no effect for bitmap based canvas
-        mCanvas.setViewport(BITMAP_HEIGHT, BITMAP_WIDTH);
-        assertEquals(BITMAP_WIDTH, mCanvas.getWidth());
-        assertEquals(BITMAP_HEIGHT, mCanvas.getHeight());
-
-        // only GL based canvas that can set viewport
-        mCanvas = new Canvas(new MyGL());
-        mCanvas.setViewport(BITMAP_HEIGHT, BITMAP_WIDTH);
-        assertEquals(BITMAP_HEIGHT, mCanvas.getWidth());
-        assertEquals(BITMAP_WIDTH, mCanvas.getHeight());
-    }
-
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "isOpaque",
@@ -2266,8 +2192,4 @@
         assertEquals(0.0f, values[7]);
         assertEquals(1.0f, values[8]);
     }
-
-    private class MyGL implements GL {
-        //do nothing
-    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/MipmapDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/MipmapDrawableTest.java
new file mode 100644
index 0000000..c591f3c
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/MipmapDrawableTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable.cts;
+
+import com.android.cts.stub.R;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.ToBeFixed;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.MipmapDrawable;
+import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.test.InstrumentationTestCase;
+import android.util.Xml;
+
+import java.io.IOException;
+
+@TestTargetClass(MipmapDrawable.class)
+public class MipmapDrawableTest extends InstrumentationTestCase {
+    private MockMipmapDrawable mMipmapDrawable;
+
+    private Resources mResources;
+
+    private DrawableContainerState mDrawableContainerState;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mMipmapDrawable = new MockMipmapDrawable();
+        mDrawableContainerState = (DrawableContainerState) mMipmapDrawable.getConstantState();
+        mResources = getInstrumentation().getTargetContext().getResources();
+    }
+
+    public void testMipmapDrawable() {
+        new MipmapDrawable();
+        // Check the values set in the constructor
+        assertNotNull(new MipmapDrawable().getConstantState());
+        assertTrue(new MockMipmapDrawable().hasCalledOnBoundsChanged());
+    }
+
+    public void testAddDrawable() {
+        assertEquals(0, mDrawableContainerState.getChildCount());
+
+        // nothing happens if drawable is null
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(null);
+        assertEquals(0, mDrawableContainerState.getChildCount());
+        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(new MockDrawable());
+        assertEquals(1, mDrawableContainerState.getChildCount());
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(new MockDrawable());
+        assertEquals(2, mDrawableContainerState.getChildCount());
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+    }
+
+    public void testSortedByHeight() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(medium, mDrawableContainerState.getChildren()[0]);
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(medium, mDrawableContainerState.getChildren()[1]);
+
+        mMipmapDrawable.addDrawable(large);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(medium, mDrawableContainerState.getChildren()[1]);
+        assertSame(large, mDrawableContainerState.getChildren()[2]);
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(large, mDrawableContainerState.getChildren()[3]);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(medium, mDrawableContainerState.getChildren()[3]);
+        assertSame(large, mDrawableContainerState.getChildren()[4]);
+
+        mMipmapDrawable.addDrawable(large);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(medium, mDrawableContainerState.getChildren()[3]);
+        assertSame(large, mDrawableContainerState.getChildren()[4]);
+        assertSame(large, mDrawableContainerState.getChildren()[5]);
+    }
+
+    public void testSetBoundsOneItem() {
+        // the method is not called if same bounds are set
+        mMipmapDrawable.reset();
+        mMipmapDrawable.setBounds(mMipmapDrawable.getBounds());
+        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // the method is called if different bounds are set, even without drawables
+        mMipmapDrawable.reset();
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // adding an item should check bounds to see if new drawable is more appropriate
+        mMipmapDrawable.reset();
+        Drawable item = new MockDrawable(42);
+        mMipmapDrawable.addDrawable(item);
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // the method is called if different bounds are set
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // check that correct drawable is selected for any size.
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() - 1));
+        assertSame(item, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight()));
+        assertSame(item, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() + 1));
+        assertSame(item, mMipmapDrawable.getCurrent());
+    }
+
+    public void testSetBounds() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        mMipmapDrawable.addDrawable(large);
+        mMipmapDrawable.addDrawable(small);
+        mMipmapDrawable.addDrawable(medium);
+
+        // check that correct drawable is selected.
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() - 1));
+        assertSame(small, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight()));
+        assertSame(small, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() + 1));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() - 1));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight()));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() + 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() - 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight()));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() + 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+    }
+
+    public void testSizes() {
+        // Check default value with no mipmap defined
+        assertEquals(-1, mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(-1, mMipmapDrawable.getIntrinsicWidth());
+        assertEquals(0, mMipmapDrawable.getMinimumHeight());
+        assertEquals(0, mMipmapDrawable.getMinimumWidth());
+
+        Drawable small = new MockDrawable(8, 4);
+        Drawable medium = new MockDrawable(32, 16);
+        Drawable large = new MockDrawable(128, 64);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertEquals(medium.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+
+        mMipmapDrawable.addDrawable(large);
+        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+
+        mMipmapDrawable.addDrawable(small);
+        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(small.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+    }
+
+    public void testReplacementWhenAdded() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        // Small bounds, so that the smallest mipmap should always be selected
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, 0));
+
+        // Providing smaller versions, that should immediately be used as current
+        mMipmapDrawable.addDrawable(large);
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mMipmapDrawable.getCurrent());
+    }
+
+    public void testInflate() throws XmlPullParserException, IOException {
+        XmlResourceParser parser = getResourceParser(R.xml.mipmap_correct);
+
+        mMipmapDrawable.reset();
+        mMipmapDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+        assertEquals(3, mDrawableContainerState.getChildCount());
+
+        // The color should be the first children
+        assertTrue(mDrawableContainerState.getChildren()[0] instanceof ColorDrawable);
+        Resources resources = getInstrumentation().getTargetContext().getResources();
+
+        parser = getResourceParser(R.xml.mipmap_missing_item_drawable);
+        try {
+            mMipmapDrawable.inflate(mResources, parser, Xml.asAttributeSet(parser));
+            fail("Should throw XmlPullParserException if drawable of item is missing");
+        } catch (XmlPullParserException e) {
+        }
+    }
+
+    @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of "
+            + "MipmapDrawable#inflate(Resources, XmlPullParser, AttributeSet) when param r,"
+            + "parser or attrs is out of bounds")
+    public void testInflateWithNullParameters() throws XmlPullParserException, IOException{
+        XmlResourceParser parser = getResourceParser(R.xml.mipmap_correct);
+        try {
+            mMipmapDrawable.inflate(null, parser, Xml.asAttributeSet(parser));
+            fail("Should throw XmlPullParserException if resource is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            mMipmapDrawable.inflate(mResources, null, Xml.asAttributeSet(parser));
+            fail("Should throw XmlPullParserException if parser is null");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            mMipmapDrawable.inflate(mResources, parser, null);
+            fail("Should throw XmlPullParserException if AttributeSet is null");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void testMutate() {
+        Resources resources = getInstrumentation().getTargetContext().getResources();
+        MipmapDrawable d1 = (MipmapDrawable) resources.getDrawable(R.drawable.mipmapdrawable);
+        MipmapDrawable d2 = (MipmapDrawable) resources.getDrawable(R.drawable.mipmapdrawable);
+        MipmapDrawable d3 = (MipmapDrawable) resources.getDrawable(R.drawable.mipmapdrawable);
+
+        // the state does not appear to be shared before calling mutate()
+        d1.addDrawable(resources.getDrawable(R.drawable.testimage));
+        assertEquals(3, ((DrawableContainerState) d1.getConstantState()).getChildCount());
+        assertEquals(2, ((DrawableContainerState) d2.getConstantState()).getChildCount());
+        assertEquals(2, ((DrawableContainerState) d3.getConstantState()).getChildCount());
+
+        // simply call mutate to make sure no exception is thrown
+        d1.mutate();
+        d2.mutate();
+    }
+
+    private XmlResourceParser getResourceParser(int resId) throws XmlPullParserException,
+            IOException {
+        XmlResourceParser parser = getInstrumentation().getTargetContext().getResources().getXml(
+                resId);
+        int type;
+        while ((type = parser.next()) != XmlPullParser.START_TAG
+                && type != XmlPullParser.END_DOCUMENT) {
+            // Empty loop
+        }
+        return parser;
+    }
+
+    private class MockMipmapDrawable extends MipmapDrawable {
+        private boolean mHasCalledOnBoundsChanged;
+
+        public boolean hasCalledOnBoundsChanged() {
+            return mHasCalledOnBoundsChanged;
+        }
+
+        public void reset() {
+            mHasCalledOnBoundsChanged = false;
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            super.onBoundsChange(bounds);
+            mHasCalledOnBoundsChanged = true;
+        }
+    }
+
+    private class MockDrawable extends Drawable {
+        int mIntrinsicHeight;
+        int mMinimumHeight;
+
+        public MockDrawable() {
+            this(0);
+        }
+
+        public MockDrawable(int intrinsicHeight) {
+            this(intrinsicHeight, intrinsicHeight);
+        }
+
+        public MockDrawable(int intrinsicHeight, int minimumHeight) {
+            mIntrinsicHeight = intrinsicHeight;
+            mMinimumHeight = minimumHeight;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mIntrinsicHeight;
+        }
+
+        @Override
+        public int getMinimumHeight() {
+            return mMinimumHeight;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index b94da11..63f5465 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -33,6 +33,15 @@
 
     private static final String TAG = "CamcorderProfileTest";
 
+    // Uses get without id if cameraId == -1 and get with id otherwise.
+    private CamcorderProfile getWithOptionalId(int quality, int cameraId) {
+        if (cameraId == -1) {
+            return CamcorderProfile.get(quality);
+        } else {
+            return CamcorderProfile.get(cameraId, quality);
+        }
+    }
+
     private void checkProfile(CamcorderProfile profile) {
         Log.v(TAG, String.format("profile: duration=%d, quality=%d, " +
             "fileFormat=%d, videoCodec=%d, videoBitRate=%d, videoFrameRate=%d, " +
@@ -52,7 +61,19 @@
             profile.audioChannels));
         assertTrue(profile.duration > 0);
         assertTrue(profile.quality == CamcorderProfile.QUALITY_LOW ||
-                   profile.quality == CamcorderProfile.QUALITY_HIGH);
+                   profile.quality == CamcorderProfile.QUALITY_HIGH ||
+                   profile.quality == CamcorderProfile.QUALITY_QCIF ||
+                   profile.quality == CamcorderProfile.QUALITY_CIF ||
+                   profile.quality == CamcorderProfile.QUALITY_480P ||
+                   profile.quality == CamcorderProfile.QUALITY_720P ||
+                   profile.quality == CamcorderProfile.QUALITY_1080P ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_LOW ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_HIGH ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_QCIF ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_CIF ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_480P ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_720P ||
+                   profile.quality == CamcorderProfile.QUALITY_TIME_LAPSE_1080P);
         assertTrue(profile.videoBitRate > 0);
         assertTrue(profile.videoFrameRate > 0);
         assertTrue(profile.videoFrameWidth > 0);
@@ -62,6 +83,128 @@
         assertTrue(profile.audioChannels > 0);
     }
 
+    private void assertProfileEquals(CamcorderProfile expectedProfile,
+            CamcorderProfile actualProfile) {
+        assertEquals(expectedProfile.duration, actualProfile.duration);
+        assertEquals(expectedProfile.fileFormat, actualProfile.fileFormat);
+        assertEquals(expectedProfile.videoCodec, actualProfile.videoCodec);
+        assertEquals(expectedProfile.videoBitRate, actualProfile.videoBitRate);
+        assertEquals(expectedProfile.videoFrameRate, actualProfile.videoFrameRate);
+        assertEquals(expectedProfile.videoFrameWidth, actualProfile.videoFrameWidth);
+        assertEquals(expectedProfile.videoFrameHeight, actualProfile.videoFrameHeight);
+        assertEquals(expectedProfile.audioCodec, actualProfile.audioCodec);
+        assertEquals(expectedProfile.audioBitRate, actualProfile.audioBitRate);
+        assertEquals(expectedProfile.audioSampleRate, actualProfile.audioSampleRate);
+        assertEquals(expectedProfile.audioChannels, actualProfile.audioChannels);
+    }
+
+    private void checkSpecificProfileDimensions(CamcorderProfile profile, int quality) {
+        Log.v(TAG, String.format("specific profile: quality=%d, width = %d, height = %d",
+                    profile.quality, profile.videoFrameWidth, profile.videoFrameHeight));
+
+        switch (quality) {
+            case CamcorderProfile.QUALITY_QCIF:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_QCIF:
+                assertEquals(176, profile.videoFrameWidth);
+                assertEquals(144, profile.videoFrameHeight);
+                break;
+
+            case CamcorderProfile.QUALITY_CIF:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_CIF:
+                assertEquals(352, profile.videoFrameWidth);
+                assertEquals(288, profile.videoFrameHeight);
+                break;
+
+            case CamcorderProfile.QUALITY_480P:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_480P:
+                assertEquals(720, profile.videoFrameWidth);
+                assertEquals(480, profile.videoFrameHeight);
+                break;
+
+            case CamcorderProfile.QUALITY_720P:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_720P:
+                assertEquals(1280, profile.videoFrameWidth);
+                assertEquals(720, profile.videoFrameHeight);
+                break;
+
+            case CamcorderProfile.QUALITY_1080P:
+            case CamcorderProfile.QUALITY_TIME_LAPSE_1080P:
+                assertEquals(1920, profile.videoFrameWidth);
+                assertEquals(1088, profile.videoFrameHeight);
+                break;
+        }
+    }
+
+    // Checks if the existing specific profiles have the correct dimensions.
+    // Also checks that the mimimum quality specific profile matches the low profile and
+    // similarly that the maximum quality specific profile matches the high profile.
+    private void checkSpecificProfiles(int cameraId,
+            CamcorderProfile low, CamcorderProfile high, int[] specificQualities) {
+        CamcorderProfile minProfile = null;
+        CamcorderProfile maxProfile = null;
+
+        for (int i = 0; i < specificQualities.length; i++) {
+            int quality = specificQualities[i];
+            if (CamcorderProfile.hasProfile(quality)) {
+                CamcorderProfile profile = getWithOptionalId(quality, cameraId);
+                checkSpecificProfileDimensions(profile, quality);
+
+                if (minProfile == null) {
+                    minProfile = profile;
+                }
+                maxProfile = profile;
+            }
+        }
+
+        assertNotNull(minProfile);
+        assertNotNull(maxProfile);
+
+        Log.v(TAG, String.format("min profile: quality=%d, width = %d, height = %d",
+                    minProfile.quality, minProfile.videoFrameWidth, minProfile.videoFrameHeight));
+        Log.v(TAG, String.format("max profile: quality=%d, width = %d, height = %d",
+                    maxProfile.quality, maxProfile.videoFrameWidth, maxProfile.videoFrameHeight));
+
+        assertProfileEquals(low, minProfile);
+        assertProfileEquals(high, maxProfile);
+    }
+
+    private void checkGet(int cameraId) {
+        Log.v(TAG, (cameraId == -1)
+                   ? "Checking get without id"
+                   : "Checking get with id = " + cameraId);
+
+        CamcorderProfile lowProfile =
+            getWithOptionalId(CamcorderProfile.QUALITY_LOW, cameraId);
+        CamcorderProfile highProfile =
+            getWithOptionalId(CamcorderProfile.QUALITY_HIGH, cameraId);
+        checkProfile(lowProfile);
+        checkProfile(highProfile);
+
+        CamcorderProfile lowTimeLapseProfile =
+            getWithOptionalId(CamcorderProfile.QUALITY_TIME_LAPSE_LOW, cameraId);
+        CamcorderProfile highTimeLapseProfile =
+            getWithOptionalId(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH, cameraId);
+        checkProfile(lowTimeLapseProfile);
+        checkProfile(highTimeLapseProfile);
+
+        int[] specificProfileQualities = {CamcorderProfile.QUALITY_QCIF,
+                                          CamcorderProfile.QUALITY_CIF,
+                                          CamcorderProfile.QUALITY_480P,
+                                          CamcorderProfile.QUALITY_720P,
+                                          CamcorderProfile.QUALITY_1080P};
+
+        int[] specificTimeLapseProfileQualities = {CamcorderProfile.QUALITY_TIME_LAPSE_QCIF,
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_CIF,
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_480P,
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_720P,
+                                                   CamcorderProfile.QUALITY_TIME_LAPSE_1080P};
+
+        checkSpecificProfiles(cameraId, lowProfile, highProfile,
+                specificProfileQualities);
+        checkSpecificProfiles(cameraId, lowTimeLapseProfile, highTimeLapseProfile,
+                specificTimeLapseProfileQualities);
+    }
+
     @TestTargets({
         @TestTargetNew(
             level = TestLevel.COMPLETE,
@@ -70,10 +213,7 @@
         )
     })
     public void testGet() {
-        CamcorderProfile lowProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
-        CamcorderProfile highProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
-        checkProfile(lowProfile);
-        checkProfile(highProfile);
+        checkGet(-1);
     }
 
     @TestTargets({
@@ -85,13 +225,8 @@
     })
     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);
+        for (int cameraId = 0; cameraId < nCamera; cameraId++) {
+            checkGet(cameraId);
         }
     }
 }
diff --git a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
index ce6658f..3974b6c 100644
--- a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorTest.java
@@ -28,9 +28,14 @@
 import android.os.Parcelable;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
 
 import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.ServerSocket;
@@ -110,6 +115,72 @@
     }
 
     @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "fromData",
+            args = {byte[].class}
+    )
+    public void testFromData() throws IOException {
+        assertNull(ParcelFileDescriptor.fromData(null, null));
+        byte[] data = new byte[] { 0 };
+        assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+        data = new byte[] { 0, 1, 2, 3 };
+        assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+        data = new byte[0];
+        assertFileDescriptorContent(data, ParcelFileDescriptor.fromData(data, null));
+
+        // Check that modifying the data does not modify the data in the FD
+        data = new byte[] { 0, 1, 2, 3 };
+        ParcelFileDescriptor pfd = ParcelFileDescriptor.fromData(data, null);
+        data[1] = 42;
+        assertFileDescriptorContent(new byte[] { 0, 1, 2, 3 }, pfd);
+    }
+
+    private static void assertFileDescriptorContent(byte[] expected, ParcelFileDescriptor fd)
+        throws IOException {
+        assertInputStreamContent(expected, new ParcelFileDescriptor.AutoCloseInputStream(fd));
+    }
+
+    private static void assertInputStreamContent(byte[] expected, InputStream is)
+            throws IOException {
+        try {
+            byte[] observed = new byte[expected.length];
+            int count = is.read(observed);
+            assertEquals(expected.length, count);
+            assertEquals(-1, is.read());
+            MoreAsserts.assertEquals(expected, observed);
+        } finally {
+            is.close();
+        }
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Tests that skip() works on FDs returned by fromData()",
+            method = "fromData",
+            args = {byte[].class}
+    )
+    public void testFromDataSkip() throws IOException {
+        byte[] data = new byte[] { 40, 41, 42, 43, 44, 45, 46 };
+        ParcelFileDescriptor pfd = ParcelFileDescriptor.fromData(data, null);
+        assertNotNull(pfd);
+        FileDescriptor fd = pfd.getFileDescriptor();
+        assertNotNull(fd);
+        assertTrue(fd.valid());
+        FileInputStream is = new FileInputStream(fd);
+        try {
+            assertEquals(1, is.skip(1));
+            assertEquals(41, is.read());
+            assertEquals(42, is.read());
+            assertEquals(2, is.skip(2));
+            assertEquals(45, is.read());
+            assertEquals(46, is.read());
+            assertEquals(-1, is.read());
+        } finally {
+            is.close();
+        }
+    }
+
+    @TestTargetNew(
         level = TestLevel.COMPLETE,
         method = "toString",
         args = {}
diff --git a/tests/tests/provider/src/android/provider/cts/SearchRecentSuggestionsTest.java b/tests/tests/provider/src/android/provider/cts/SearchRecentSuggestionsTest.java
new file mode 100644
index 0000000..f17ecf9
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/SearchRecentSuggestionsTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.SearchRecentSuggestions;
+import android.test.ProviderTestCase2;
+
+@TestTargetClass(android.provider.SearchRecentSuggestions.class)
+public class SearchRecentSuggestionsTest extends
+        ProviderTestCase2<TestSearchRecentSuggestionsProvider> {
+    private final static String AUTHORITY_HEAD = "content://"
+            + TestSearchRecentSuggestionsProvider.AUTHORITY;
+
+    private Uri mTestUri;
+    private TestSearchRecentSuggestionsProvider mTestSRSProvider;
+    private Context mContext;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mTestUri = Uri.parse(AUTHORITY_HEAD + "/suggestions");
+        mTestSRSProvider = getProvider();
+        mContext = mTestSRSProvider.getContext();
+    }
+
+    public SearchRecentSuggestionsTest() {
+        super(TestSearchRecentSuggestionsProvider.class,
+                TestSearchRecentSuggestionsProvider.AUTHORITY);
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "SearchRecentSuggestions",
+        args = {android.content.Context.class, java.lang.String.class, int.class}
+    )
+    public void testConstructor() {
+        new SearchRecentSuggestions(mContext, TestSearchRecentSuggestionsProvider.AUTHORITY,
+                TestSearchRecentSuggestionsProvider.MODE);
+    }
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "SearchRecentSuggestions",
+            args = {android.content.Context.class, java.lang.String.class, int.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "saveRecentQuery",
+            args = {java.lang.String.class, java.lang.String.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "clearHistory",
+            args = {}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "truncateHistory",
+            args = {android.content.ContentResolver.class, int.class}
+        )
+    })
+    public void testSearchRecentSuggestions() {
+        MySearchRecentSuggestions srs = new MySearchRecentSuggestions(mContext,
+                TestSearchRecentSuggestionsProvider.AUTHORITY,
+                TestSearchRecentSuggestionsProvider.MODE);
+        Cursor c = mTestSRSProvider.query(mTestUri, null, null, null, null);
+
+        try {
+            assertNotNull(c);
+            assertEquals(0, c.getCount());
+            c.close();
+
+            // insert three rows
+            String query1 = "query1";
+            String line1 = "line1";
+            srs.saveRecentQuery(query1, line1);
+            c = mTestSRSProvider.query(mTestUri, SearchRecentSuggestions.QUERIES_PROJECTION_2LINE,
+                    null, null, null);
+            assertNotNull(c);
+            assertEquals(1, c.getCount());
+
+            c.moveToFirst();
+            assertEquals(query1, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_QUERY_INDEX));
+            assertEquals(line1, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_DISPLAY2_INDEX));
+            c.close();
+
+            String query2 = "query2";
+            String line2 = "line2";
+            srs.saveRecentQuery(query2, line2);
+            c = mTestSRSProvider.query(mTestUri, null, null, null, null);
+            assertNotNull(c);
+            assertEquals(2, c.getCount());
+            c.close();
+
+            String query3 = "query3";
+            String line3 = "line3";
+            srs.saveRecentQuery(query3, line3);
+            c = mTestSRSProvider.query(mTestUri, null, null, null, null);
+            assertNotNull(c);
+            assertEquals(3, c.getCount());
+            c.close();
+
+            // truncateHistory will delete the oldest one record
+            ContentResolver cr = mContext.getContentResolver();
+            srs.truncateHistory(cr, 2);
+            c = mTestSRSProvider.query(mTestUri, SearchRecentSuggestions.QUERIES_PROJECTION_2LINE,
+                    null, null, null);
+            assertNotNull(c);
+            assertEquals(2, c.getCount());
+
+            // and the left two should be: test2 and test3, test1 should be delete
+            c.moveToFirst();
+            assertEquals(query2, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_QUERY_INDEX));
+            assertEquals(line2, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_DISPLAY2_INDEX));
+            c.moveToNext();
+            assertEquals(query3, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_QUERY_INDEX));
+            assertEquals(line3, c
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_DISPLAY2_INDEX));
+            c.close();
+
+            // clear all history
+            srs.clearHistory();
+            c = mTestSRSProvider.query(mTestUri, null, null, null, null);
+            assertNotNull(c);
+            assertEquals(0, c.getCount());
+        } finally {
+            c.close();
+        }
+    }
+
+    public void testSuggestionsTable() {
+        String insertDisplay1 = "display1_insert";
+        String insertDisplay2 = "display2_insert";
+        String insertQuery = "query_insert";
+
+        String updateDisplay1 = "display1_update";
+        String updateDisplay2 = "display2_update";
+        String updateQuery = "query_update";
+
+        // Test: insert
+        ContentValues value = new ContentValues();
+        value.put("display1", insertDisplay1);
+        value.put("display2", insertDisplay2);
+        value.put("query", insertQuery);
+        value.put("date", 1);
+
+        mTestSRSProvider.insert(mTestUri, value);
+
+        Cursor cursor = mTestSRSProvider.query(mTestUri,
+                SearchRecentSuggestions.QUERIES_PROJECTION_2LINE,
+                "display1=\"" + insertDisplay1 + "\"", null, null);
+        try {
+            assertNotNull(cursor);
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToFirst());
+            assertEquals(insertDisplay2, cursor
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_DISPLAY2_INDEX));
+            assertEquals(insertQuery, cursor
+                    .getString(SearchRecentSuggestions.QUERIES_PROJECTION_QUERY_INDEX));
+            assertEquals(1, cursor.getInt(SearchRecentSuggestions.QUERIES_PROJECTION_DATE_INDEX));
+            cursor.close();
+
+            // Test: update
+            /**
+             * SearchRecentSuggestionsProvider.update is not implement, always
+             * throw an UnsupportedOperationException.
+             */
+            value.clear();
+            value.put("display1", updateDisplay1);
+            value.put("display2", updateDisplay2);
+            value.put("query", updateQuery);
+            value.put("date", 2);
+
+            try {
+                mTestSRSProvider.update(mTestUri, value, "display1=\"" + insertDisplay1 + "\"",
+                        null);
+                fail("There should be an UnsupportedOperationException thrown out.");
+            } catch (UnsupportedOperationException e) {
+                // expected, test success.
+            }
+
+            // Test: delete
+            mTestSRSProvider.delete(mTestUri, "display1=\"" + insertDisplay1 + "\"", null);
+            cursor = mTestSRSProvider.query(mTestUri,
+                    SearchRecentSuggestions.QUERIES_PROJECTION_2LINE, "display1=\""
+                            + insertDisplay1 + "\"", null, null);
+            assertNotNull(cursor);
+            assertEquals(0, cursor.getCount());
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private class MySearchRecentSuggestions extends SearchRecentSuggestions {
+        public MySearchRecentSuggestions(Context context, String authority, int mode) {
+            super(context, authority, mode);
+        }
+
+        protected void truncateHistory(ContentResolver cr, int maxEntries) {
+            super.truncateHistory(cr, maxEntries);
+        }
+    }
+}
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
index 26ebfb5..f8b4336 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
@@ -16,6 +16,12 @@
 
 package android.text.cts;
 
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.ToBeFixed;
+
 import android.test.AndroidTestCase;
 import android.text.InputFilter;
 import android.text.SpannableString;
@@ -24,11 +30,6 @@
 import android.text.style.StrikethroughSpan;
 import android.text.style.TabStopSpan;
 import android.text.style.UnderlineSpan;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.ToBeFixed;
 
 /**
  * Test {@link SpannableStringBuilder}.
@@ -250,6 +251,28 @@
         builder.replace(0, 5, text, 0, text.length());
         assertEquals("ahiabc, world", builder.toString());
 
+        // Replacing by an empty string (identical target indexes)
+        builder = new SpannableStringBuilder("hello, world");
+        builder.replace(4, 6, "", 0, 0);
+        assertEquals("hell world", builder.toString());
+
+        builder = new SpannableStringBuilder("hello, world");
+        builder.replace(4, 6, "any string", 5, 5);
+        assertEquals("hell world", builder.toString());
+
+        // Inserting in place (no deletion)
+        builder = new SpannableStringBuilder("hello, world");
+        builder.replace(3, 3, "any string", 0, 0);
+        assertEquals("hello, world", builder.toString());
+
+        builder = new SpannableStringBuilder("hello, world");
+        builder.replace(7, 7, "nice ", 0, 5);
+        assertEquals("hello, nice world", builder.toString());
+
+        builder = new SpannableStringBuilder("hello, world");
+        builder.replace(0, 0, "say ", 1, 4);
+        assertEquals("ay hello, world", builder.toString());
+
         try {
             builder.replace(0, 5, text, 10, 3);
             fail("should throw IndexOutOfBoundsException here");
diff --git a/tests/tests/view/src/android/view/cts/AccessibilityEventTest.java b/tests/tests/view/src/android/view/cts/AccessibilityEventTest.java
index 731784a..f7c1e7a 100644
--- a/tests/tests/view/src/android/view/cts/AccessibilityEventTest.java
+++ b/tests/tests/view/src/android/view/cts/AccessibilityEventTest.java
@@ -202,8 +202,7 @@
         TestCase.assertEquals("fromIndex not properly recycled", 0, event.getFromIndex());
         TestCase.assertEquals("itemCount not properly recycled", 0, event.getItemCount());
         TestCase.assertNull("packageName not properly recycled", event.getPackageName());
-        // This will fail and is fixed in Gingerbread Bug: 2593810
-        // TestCase.assertNull("parcelableData not properly recycled", event.getParcelableData());
+        TestCase.assertNull("parcelableData not properly recycled", event.getParcelableData());
         TestCase.assertEquals("removedCount not properly recycled", 0, event.getRemovedCount());
         TestCase.assertTrue("text not properly recycled", event.getText().isEmpty());
     }
diff --git a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
index 6f637fc..f5bd8f4 100644
--- a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
@@ -16,6 +16,14 @@
 
 package android.view.cts;
 
+import com.android.cts.stub.R;
+import com.android.internal.util.XmlUtils;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.cts.MockActivity;
@@ -23,6 +31,7 @@
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
@@ -35,21 +44,13 @@
 import android.view.LayoutInflater.Factory;
 import android.view.LayoutInflater.Filter;
 import android.widget.LinearLayout;
-import com.android.cts.stub.R;
-
-import com.android.internal.util.XmlUtils;
-
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
 
 @TestTargetClass(LayoutInflater.class)
 public class LayoutInflaterTest extends AndroidTestCase {
 
     private LayoutInflater mLayoutInflater;
     private Context mContext;
-    private Factory mFactory = new Factory() {
+    private final Factory mFactory = new Factory() {
         public View onCreateView(String name, Context context,
                 AttributeSet attrs) {
 
@@ -57,7 +58,7 @@
         }
     };
     private boolean isOnLoadClass;
-    private Filter mFilter = new Filter() {
+    private final Filter mFilter = new Filter() {
 
         @SuppressWarnings("unchecked")
         public boolean onLoadClass(Class clazz) {
@@ -172,7 +173,7 @@
             }
             String nodeName = parser.getName();
             if (!"alias".equals(nodeName)) {
-                throw new RuntimeException();
+                throw new InflateException();
             }
             int outerDepth = parser.getDepth();
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -296,8 +297,7 @@
         try {
             view = mLayoutInflater.inflate(-1, null);
             fail("should throw exception");
-        } catch (RuntimeException e) {
-
+        } catch (Resources.NotFoundException e) {
         }
         LinearLayout mLayout;
         mLayout = new LinearLayout(mContext);
@@ -335,7 +335,7 @@
         try {
             view = mLayoutInflater.inflate(-1, null, false);
             fail("should throw exception");
-        } catch (RuntimeException e) {
+        } catch (Resources.NotFoundException e) {
 
         }
         LinearLayout mLayout;
@@ -381,7 +381,7 @@
         try {
             view = mLayoutInflater.inflate(null, null);
             fail("should throw exception");
-        } catch (RuntimeException e) {
+        } catch (NullPointerException e) {
         }
         LinearLayout mLayout;
         mLayout = new LinearLayout(mContext);
@@ -395,7 +395,7 @@
         try {
             view = mLayoutInflater.inflate(parser, mLayout);
             fail("should throw exception");
-        } catch (RuntimeException e) {
+        } catch (NullPointerException e) {
         }
         parser = getContext().getResources().getLayout(
                 R.layout.inflater_layout);
@@ -440,7 +440,7 @@
        try {
            view = mLayoutInflater.inflate(null, null, false);
            fail("should throw exception");
-       } catch (RuntimeException e) {
+       } catch (NullPointerException e) {
        }
        LinearLayout mLayout;
        mLayout = new LinearLayout(mContext);
@@ -454,7 +454,7 @@
        try {
            view = mLayoutInflater.inflate(parser, mLayout, false);
            fail("should throw exception");
-       } catch (RuntimeException e) {
+       } catch (NullPointerException e) {
        }
        parser = getContext().getResources().getLayout(
                R.layout.inflater_layout);
@@ -475,7 +475,7 @@
        try {
            view = mLayoutInflater.inflate(parser, mLayout, false);
            fail("should throw exception");
-       } catch (RuntimeException e) {
+       } catch (InflateException e) {
        }
 
        parser = null;
@@ -497,6 +497,7 @@
             super(original, newContext);
         }
 
+        @Override
         public View onCreateView(String name, AttributeSet attrs)
                 throws ClassNotFoundException {
             return super.onCreateView(name, attrs);
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 3168312..871985c 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -47,6 +47,8 @@
 import android.util.SparseArray;
 import android.util.Xml;
 import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.ActionMode;
 import android.view.Display;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
@@ -54,11 +56,6 @@
 import android.view.SoundEffectConstants;
 import android.view.TouchDelegate;
 import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.WindowManagerImpl;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.view.View.BaseSavedState;
 import android.view.View.OnClickListener;
 import android.view.View.OnCreateContextMenuListener;
@@ -66,6 +63,10 @@
 import android.view.View.OnKeyListener;
 import android.view.View.OnLongClickListener;
 import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.WindowManagerImpl;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.cts.DelayedCheck;
@@ -4626,6 +4627,11 @@
             return false;
         }
 
+        public ActionMode startActionModeForChild(View originalView,
+                ActionMode.Callback callback) {
+            return null;
+        }
+
         public boolean hasShowContextMenuForChild() {
             return mHasShowContextMenuForChild;
         }
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index 0e31888..60947b5 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -37,7 +37,7 @@
 import android.os.Bundle;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.DisplayMetrics;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.InputQueue;
 import android.view.KeyEvent;
@@ -50,6 +50,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.TextView;
 
 @TestTargetClass(Window.class)
@@ -1148,6 +1149,9 @@
         public void togglePanel(int featureId, KeyEvent event) {
         }
 
+        public void invalidatePanelMenu(int featureId) {
+        }
+        
         public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
             return true;
         }
@@ -1326,5 +1330,9 @@
         public boolean onSearchRequested() {
             return false;
         }
+
+        public ActionMode onStartActionMode(ActionMode.Callback callback) {
+            return null;
+        }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java b/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java
new file mode 100644
index 0000000..8175807
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListTester.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget.cts;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.cts.util.ExpandableListScenario;
+import android.widget.cts.util.ListUtil;
+
+import junit.framework.Assert;
+
+public class ExpandableListTester {
+    private final ExpandableListView mExpandableListView;
+    private final ExpandableListAdapter mAdapter;
+    private final ListUtil mListUtil;
+
+    private final ActivityInstrumentationTestCase2<? extends ExpandableListScenario>
+        mActivityInstrumentation;
+
+    Instrumentation mInstrumentation;
+
+    public ExpandableListTester(
+            ExpandableListView expandableListView,
+            ActivityInstrumentationTestCase2<? extends ExpandableListScenario>
+            activityInstrumentation) {
+        mExpandableListView = expandableListView;
+        Instrumentation instrumentation = activityInstrumentation.getInstrumentation();
+        mListUtil = new ListUtil(mExpandableListView, instrumentation);
+        mAdapter = mExpandableListView.getExpandableListAdapter();
+        mActivityInstrumentation = activityInstrumentation;
+        mInstrumentation = mActivityInstrumentation.getInstrumentation();
+    }
+
+    private void expandGroup(final int groupIndex, int flatPosition) {
+        Assert.assertFalse("Group is already expanded", mExpandableListView
+                .isGroupExpanded(groupIndex));
+        mListUtil.arrowScrollToSelectedPosition(flatPosition);
+        mInstrumentation.waitForIdleSync();
+        mActivityInstrumentation.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        mActivityInstrumentation.getInstrumentation().waitForIdleSync();
+        Assert.assertTrue("Group did not expand " + groupIndex, 
+                mExpandableListView.isGroupExpanded(groupIndex));
+    }
+
+    void testContextMenus() {
+        // Add a position tester ContextMenu listener to the ExpandableListView
+        PositionTesterContextMenuListener menuListener = new PositionTesterContextMenuListener();
+        mExpandableListView.setOnCreateContextMenuListener(menuListener);
+
+        int index = 0;
+
+        // Scrolling on header elements should trigger an AdapterContextMenu
+        for (int i=0; i<mExpandableListView.getHeaderViewsCount(); i++) {
+            // Check group index in context menu
+            menuListener.expectAdapterContextMenu(i);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View headerChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(headerChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+        }
+
+        int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+
+            // Expand group
+            expandGroup(groupIndex, index);
+
+            // Check group index in context menu
+            menuListener.expectGroupContextMenu(groupIndex);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View groupChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(groupChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+
+            final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+            for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+                // Check child index in context menu
+                mListUtil.arrowScrollToSelectedPosition(index);
+                menuListener.expectChildContextMenu(groupIndex, childIndex);
+                View child = mExpandableListView.getChildAt(index
+                        - mExpandableListView.getFirstVisiblePosition());
+                mExpandableListView.showContextMenuForChild(child);
+                mInstrumentation.waitForIdleSync();
+                Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+                index++;
+            }
+        }
+
+        // Scrolling on footer elements should trigger an AdapterContextMenu
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            // Check group index in context menu
+            menuListener.expectAdapterContextMenu(index);
+            // Make sure the group is visible so that getChild finds it
+            mListUtil.arrowScrollToSelectedPosition(index);
+            View footerChild = mExpandableListView.getChildAt(index
+                    - mExpandableListView.getFirstVisiblePosition());
+            mExpandableListView.showContextMenuForChild(footerChild);
+            mInstrumentation.waitForIdleSync();
+            Assert.assertNull(menuListener.getErrorMessage(), menuListener.getErrorMessage());
+            index++;
+        }
+
+        // Cleanup: remove the listener we added.
+        mExpandableListView.setOnCreateContextMenuListener(null);
+    }
+
+    private int expandAGroup() {
+        final int groupIndex = 2;
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        Assert.assertTrue("Not enough groups", groupIndex < mAdapter.getGroupCount());
+        expandGroup(groupIndex, groupIndex + headerCount);
+        return groupIndex;
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testConvertionBetweenFlatAndPackedOnGroups() {
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+
+        for (int i=0; i<headerCount; i++) {
+            Assert.assertEquals("Non NULL position for header item",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getExpandableListPosition(i));
+        }
+
+        // Test all (non expanded) groups
+        final int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+            int expectedFlatPosition = headerCount + groupIndex;
+            long packedPositionForGroup = ExpandableListView.getPackedPositionForGroup(groupIndex);
+            Assert.assertEquals("Group not found at flat position " + expectedFlatPosition,
+                    packedPositionForGroup,
+                    mExpandableListView.getExpandableListPosition(expectedFlatPosition));
+
+            Assert.assertEquals("Wrong flat position for group " + groupIndex,
+                    expectedFlatPosition,
+                    mExpandableListView.getFlatListPosition(packedPositionForGroup));
+        }
+
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            Assert.assertEquals("Non NULL position for header item",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getExpandableListPosition(headerCount + groupCount + i));
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testConvertionBetweenFlatAndPackedOnChildren() {
+        // Test with an expanded group
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        final int groupIndex = expandAGroup();
+
+        final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+        for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+            int expectedFlatPosition = headerCount + groupIndex + 1 + childIndex;
+            long childPos = ExpandableListView.getPackedPositionForChild(groupIndex, childIndex);
+
+            Assert.assertEquals("Wrong flat position for child ",
+                    childPos,
+                    mExpandableListView.getExpandableListPosition(expectedFlatPosition));
+
+            Assert.assertEquals("Wrong flat position for child ",
+                    expectedFlatPosition,
+                    mExpandableListView.getFlatListPosition(childPos));
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testSelectedPositionOnGroups() {
+        int index = 0;
+
+        // Scrolling on header elements should not give a valid selected position.
+        for (int i=0; i<mExpandableListView.getHeaderViewsCount(); i++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Header item is selected",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+
+        // Check selection on group items
+        final int groupCount = mAdapter.getGroupCount();
+        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Group item is not selected",
+                    ExpandableListView.getPackedPositionForGroup(groupIndex),
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+
+        // Scrolling on footer elements should not give a valid selected position.
+        for (int i=0; i<mExpandableListView.getFooterViewsCount(); i++) {
+            mListUtil.arrowScrollToSelectedPosition(index);
+            Assert.assertEquals("Footer item is selected",
+                    ExpandableListView.PACKED_POSITION_VALUE_NULL,
+                    mExpandableListView.getSelectedPosition());
+            index++;
+        }
+    }
+
+    // This method assumes that NO group is expanded when called
+    void testSelectedPositionOnChildren() {
+        // Test with an expanded group
+        final int headerCount = mExpandableListView.getHeaderViewsCount();
+        final int groupIndex = expandAGroup();
+
+        final int childrenCount = mAdapter.getChildrenCount(groupIndex);
+        for (int childIndex = 0; childIndex < childrenCount; childIndex++) {
+            int childFlatPosition = headerCount + groupIndex + 1 + childIndex;
+            mListUtil.arrowScrollToSelectedPosition(childFlatPosition);
+            Assert.assertEquals("Group item is not selected",
+                    ExpandableListView.getPackedPositionForChild(groupIndex, childIndex),
+                    mExpandableListView.getSelectedPosition());
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
index c6c0b35..fc39364 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
@@ -16,7 +16,10 @@
 
 package android.widget.cts;
 
-import java.util.List;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
 
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -27,21 +30,19 @@
 import android.widget.cts.util.ExpandableListScenario;
 import android.widget.cts.util.ListUtil;
 import android.widget.cts.util.ExpandableListScenario.MyGroup;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
+
+import java.util.List;
 
 @TestTargetClass(ExpandableListView.class)
 public class ExpandableListViewBasicTest extends
         ActivityInstrumentationTestCase2<ExpandableListSimple> {
     private ExpandableListScenario mActivity;
-    private ExpandableListView mListView;
+    private ExpandableListView mExpandableListView;
     private ExpandableListAdapter mAdapter;
     private ListUtil mListUtil;
 
     public ExpandableListViewBasicTest() {
-        super("com.android.cts.stub", ExpandableListSimple.class);
+        super(ExpandableListSimple.class);
     }
 
     @Override
@@ -49,27 +50,27 @@
         super.setUp();
 
         mActivity = getActivity();
-        mListView = mActivity.getExpandableListView();
-        mAdapter = mListView.getExpandableListAdapter();
-        mListUtil = new ListUtil(mListView, getInstrumentation());
+        mExpandableListView = mActivity.getExpandableListView();
+        mAdapter = mExpandableListView.getExpandableListAdapter();
+        mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
     }
 
     @MediumTest
     public void testPreconditions() {
         assertNotNull(mActivity);
-        assertNotNull(mListView);
+        assertNotNull(mExpandableListView);
     }
 
     private int expandGroup(int numChildren, boolean atLeastOneChild) {
         final int groupPos = mActivity.findGroupWithNumChildren(numChildren, atLeastOneChild);
 
         assertTrue("Could not find group to expand", groupPos >= 0);
-        assertFalse("Group is already expanded", mListView.isGroupExpanded(groupPos));
+        assertFalse("Group is already expanded", mExpandableListView.isGroupExpanded(groupPos));
         mListUtil.arrowScrollToSelectedPosition(groupPos);
         getInstrumentation().waitForIdleSync();
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
         getInstrumentation().waitForIdleSync();
-        assertTrue("Group did not expand", mListView.isGroupExpanded(groupPos));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(groupPos));
 
         return groupPos;
     }
@@ -97,7 +98,7 @@
 
         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
         getInstrumentation().waitForIdleSync();
-        assertFalse("Group did not collapse", mListView.isGroupExpanded(groupPos));
+        assertFalse("Group did not collapse", mExpandableListView.isGroupExpanded(groupPos));
     }
 
     @TestTargets({
@@ -122,13 +123,13 @@
         getInstrumentation().waitForIdleSync();
 
         // Ensure it expanded
-        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
 
         // Wait until that's all good
         getInstrumentation().waitForIdleSync();
 
         // Make sure it expanded
-        assertTrue("Group did not expand", mListView.isGroupExpanded(0));
+        assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
 
         // Insert a collapsed group in front of the one just expanded
         List<MyGroup> groups = mActivity.getGroups();
@@ -149,8 +150,28 @@
 
         // Make sure the right group is expanded
         assertTrue("The expanded state didn't stay with the proper group",
-                mListView.isGroupExpanded(1));
+                mExpandableListView.isGroupExpanded(1));
         assertFalse("The expanded state was given to the inserted group",
-                mListView.isGroupExpanded(0));
+                mExpandableListView.isGroupExpanded(0));
+    }
+
+    @MediumTest
+    public void testContextMenus() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testContextMenus();
+    }
+
+    @MediumTest
+    public void testConvertionBetweenFlatAndPacked() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testConvertionBetweenFlatAndPackedOnGroups();
+        tester.testConvertionBetweenFlatAndPackedOnChildren();
+    }
+
+    @MediumTest
+    public void testSelectedPosition() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testSelectedPositionOnGroups();
+        tester.testSelectedPositionOnChildren();
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index af420b4..5ab7f4d 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -519,10 +519,10 @@
         args = {int.class, int.class}
     )
     public void testGetPackedPositionForChild() {
-        assertEquals((long) 0x8000000000000000L,
+        assertEquals(0x8000000000000000L,
                 ExpandableListView.getPackedPositionForChild(0, 0));
 
-        assertEquals((long) 0xffffffffffffffffL,
+        assertEquals(0xffffffffffffffffL,
                 ExpandableListView.getPackedPositionForChild(Integer.MAX_VALUE, 0xffffffff));
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
index 57776a0..fe65f98 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
@@ -16,16 +16,16 @@
 
 package android.widget.cts;
 
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.ExpandableListView;
 import android.widget.cts.util.ListUtil;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
 
 @TestTargetClass(ExpandableListView.class)
 public class ExpandableListViewWithHeadersTest extends
@@ -34,7 +34,7 @@
     private ListUtil mListUtil;
 
     public ExpandableListViewWithHeadersTest() {
-        super("com.android.cts.stub", ExpandableListWithHeaders.class);
+        super(ExpandableListWithHeaders.class);
     }
 
     @Override
@@ -78,4 +78,24 @@
         getInstrumentation().waitForIdleSync();
         assertTrue(mExpandableListView.isGroupExpanded(0));
     }
+
+    @MediumTest
+    public void testContextMenus() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testContextMenus();
+    }
+
+    @MediumTest
+    public void testConvertionBetweenFlatAndPacked() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testConvertionBetweenFlatAndPackedOnGroups();
+        tester.testConvertionBetweenFlatAndPackedOnChildren();
+    }
+
+    @MediumTest
+    public void testSelectedPosition() {
+        ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
+        tester.testSelectedPositionOnGroups();
+        tester.testSelectedPositionOnChildren();
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 65045d8..376c137 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -531,6 +531,48 @@
             assertEquals(0, child.getLeft() - mGridView.getListPaddingLeft());
         }
     }
+    
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test {@link GridView#getNumColumns()}",
+        method = "getNumColumns"
+    )
+    public void testGetNumColumns() {
+        mGridView = new GridView(mActivity);
+        
+        assertEquals(mGridView.getNumColumns(), GridView.AUTO_FIT);
+        
+        mGridView = findGridViewById(R.id.gridview);
+        
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setAdapter(new MockGridViewAdapter(10));
+                mGridView.setNumColumns(10);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        
+        assertEquals(mGridView.getNumColumns(), 10);
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setNumColumns(1);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        
+        assertEquals(mGridView.getNumColumns(), 1);
+
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mGridView.setNumColumns(0);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        
+        //although setNumColumns(0) was called, the number of columns should be 1
+        assertEquals(mGridView.getNumColumns(), 1);
+    }
 
     @TestTargetNew(
         level = TestLevel.COMPLETE,
diff --git a/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java b/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java
new file mode 100644
index 0000000..a1c9bc4
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/PositionTesterContextMenuListener.java
@@ -0,0 +1,111 @@
+/*
+ * 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.widget.cts;
+
+import android.view.ContextMenu;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View.OnCreateContextMenuListener;
+import android.widget.ExpandableListView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class PositionTesterContextMenuListener implements OnCreateContextMenuListener {
+
+    private int groupPosition, childPosition;
+
+    // Fake constant to store in testType a test type specific to headers and footers
+    private static final int ADAPTER_TYPE = -1;
+    private int testType; // as returned by getPackedPositionType
+
+    // Will be set to null by each call to onCreateContextMenu, unless an error occurred. 
+    private String errorMessage;
+
+    public void expectGroupContextMenu(int groupPosition) {
+        this.groupPosition = groupPosition;
+        testType = ExpandableListView.PACKED_POSITION_TYPE_GROUP;
+    }
+
+    public void expectChildContextMenu(int groupPosition, int childPosition) {
+        this.groupPosition = groupPosition;
+        this.childPosition = childPosition;
+        testType = ExpandableListView.PACKED_POSITION_TYPE_CHILD;
+    }
+
+    public void expectAdapterContextMenu(int flatPosition) {
+        this.groupPosition = flatPosition;
+        testType = ADAPTER_TYPE;
+    }
+
+    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+        errorMessage = null;
+        if (testType == ADAPTER_TYPE) {
+            if (!isTrue("MenuInfo is not an AdapterContextMenuInfo",
+                    menuInfo instanceof AdapterContextMenuInfo)) {
+                return;
+            }
+            AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo;
+            if (!areEqual("Wrong flat position", groupPosition, adapterContextMenuInfo.position)) {
+                return;
+            }
+        } else {
+            if (!isTrue("MenuInfo is not an ExpandableListContextMenuInfo",
+                    menuInfo instanceof ExpandableListView.ExpandableListContextMenuInfo)) {
+                return;
+            }
+            ExpandableListView.ExpandableListContextMenuInfo elvMenuInfo =
+                (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
+            long packedPosition = elvMenuInfo.packedPosition;
+
+            int packedPositionType = ExpandableListView.getPackedPositionType(packedPosition);
+            if (!areEqual("Wrong packed position type", testType, packedPositionType)) {
+                return;
+            }
+
+            int packedPositionGroup = ExpandableListView.getPackedPositionGroup(packedPosition);
+            if (!areEqual("Wrong group position", groupPosition, packedPositionGroup)) {
+                return;
+            }
+
+            if (testType == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+                int packedPositionChild = ExpandableListView.getPackedPositionChild(packedPosition);
+                if (!areEqual("Wrong child position", childPosition, packedPositionChild)) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private boolean areEqual(String message, int expected, int actual) {
+        if (expected != actual) {
+            errorMessage = String.format(message + " (%d vs %d", expected, actual);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean isTrue(String message, boolean value) {
+        if (!value) {
+            errorMessage = message;
+            return false;
+        }
+        return true;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+}