Merge "Turn off pulsing jogball while on a call."
diff --git a/common/java/com/android/common/speech/Recognition.java b/common/java/com/android/common/speech/Recognition.java
index a79a19b..1970179 100644
--- a/common/java/com/android/common/speech/Recognition.java
+++ b/common/java/com/android/common/speech/Recognition.java
@@ -55,6 +55,7 @@
     public static final int HINT_CONTEXT_UNKNOWN = 0;
     public static final int HINT_CONTEXT_VOICE_SEARCH_HELP = 1;
     public static final int HINT_CONTEXT_CAR_HOME = 2;
+    public static final int HINT_CONTEXT_LAUNCHER = 3;
 
     private Recognition() { }   // don't instantiate
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8695598..3c5a1c7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -819,7 +819,7 @@
     /**
      * This method is called after {@link #onStart} when the activity is
      * being re-initialized from a previously saved state, given here in
-     * <var>state</var>.  Most implementations will simply use {@link #onCreate}
+     * <var>savedInstanceState</var>.  Most implementations will simply use {@link #onCreate}
      * to restore their state, but it is sometimes convenient to do it here
      * after all of the initialization has been done or to allow subclasses to
      * decide whether to use your default implementation.  The default
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 3dd3918..b827af8 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -117,7 +117,10 @@
      * exception.
      *
      * Verification of a package can take significant time, so this
-     * function should not be called from a UI thread.
+     * function should not be called from a UI thread.  Interrupting
+     * the thread while this function is in progress will result in a
+     * SecurityException being thrown (and the thread's interrupt flag
+     * will be cleared).
      *
      * @param packageFile  the package to be verified
      * @param listener     an object to receive periodic progress
@@ -259,7 +262,10 @@
             long soFar = 0;
             raf.seek(0);
             byte[] buffer = new byte[4096];
+            boolean interrupted = false;
             while (soFar < toRead) {
+                interrupted = Thread.interrupted();
+                if (interrupted) break;
                 int size = buffer.length;
                 if (soFar + size > toRead) {
                     size = (int)(toRead - soFar);
@@ -283,6 +289,10 @@
                 listener.onProgress(100);
             }
 
+            if (interrupted) {
+                throw new SignatureException("verification was interrupted");
+            }
+
             if (!sig.verify(sigInfo.getEncryptedDigest())) {
                 throw new SignatureException("signature digest verification failed");
             }
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 85efea3..a5c85c1 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -608,22 +608,24 @@
      */
     public static final void requestAllIcons(ContentResolver cr, String where,
             WebIconDatabase.IconListener listener) {
+        Cursor c = null;
         try {
-            final Cursor c = cr.query(
+            c = cr.query(
                     BOOKMARKS_URI,
-                    HISTORY_PROJECTION,
+                    new String[] { BookmarkColumns.URL },
                     where, null, null);
             if (c.moveToFirst()) {
                 final WebIconDatabase db = WebIconDatabase.getInstance();
                 do {
-                    db.requestIconForPageUrl(
-                            c.getString(HISTORY_PROJECTION_URL_INDEX), 
-                            listener);
+                    db.requestIconForPageUrl(c.getString(0), listener);
                 } while (c.moveToNext());
             }
-            c.deactivate();
         } catch (IllegalStateException e) {
             Log.e(LOGTAG, "requestAllIcons", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
         }
     }
 
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 509317d..4dbeef9 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -52,8 +52,7 @@
     /**
      * Broadcast Action: An event reminder.
      */
-    public static final String
-            EVENT_REMINDER_ACTION = "android.intent.action.EVENT_REMINDER";
+    public static final String EVENT_REMINDER_ACTION = "android.intent.action.EVENT_REMINDER";
 
     /**
      * These are the symbolic names for the keys used in the extra data
@@ -208,6 +207,9 @@
      */
     public static class Calendars implements BaseColumns, CalendarsColumns
     {
+        private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars._SYNC_ACCOUNT + "=?"
+                + " AND " + Calendars._SYNC_ACCOUNT_TYPE + "=?";
+
         public static final Cursor query(ContentResolver cr, String[] projection,
                                        String where, String orderBy)
         {
@@ -237,16 +239,14 @@
         public static int deleteCalendarsForAccount(ContentResolver cr, Account account) {
             // delete all calendars that match this account
             return Calendar.Calendars.delete(cr,
-                    Calendar.Calendars._SYNC_ACCOUNT + "=? AND "
-                            + Calendar.Calendars._SYNC_ACCOUNT_TYPE + "=?",
-                    new String[] {account.name, account.type});
+                    WHERE_DELETE_FOR_ACCOUNT,
+                    new String[] { account.name, account.type });
         }
 
         /**
          * The content:// style URL for this table
          */
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/calendars");
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/calendars");
 
         /**
          * The default sort order for this table
@@ -346,10 +346,8 @@
         public static final int ATTENDEE_STATUS_TENTATIVE = 4;
     }
 
-    public static final class Attendees implements BaseColumns,
-            AttendeesColumns, EventsColumns {
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://" + AUTHORITY + "/attendees");
+    public static final class Attendees implements BaseColumns, AttendeesColumns, EventsColumns {
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/attendees");
 
         // TODO: fill out this class when we actually start utilizing attendees
         // in the calendar application.
@@ -641,6 +639,8 @@
             private static final int COLUMN_NAME = 0;
             private static final int COLUMN_VALUE = 1;
 
+            private static final String WHERE_EVENT_ID = "event_id=?";
+
             public EntityIteratorImpl(Cursor cursor, ContentResolver resolver) {
                 super(cursor);
                 mResolver = resolver;
@@ -703,10 +703,14 @@
                 Cursor subCursor;
                 if (mResolver != null) {
                     subCursor = mResolver.query(Reminders.CONTENT_URI, REMINDERS_PROJECTION,
-                            "event_id=" + eventId, null, null);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) }  /* selectionArgs */,
+                            null /* sortOrder */);
                 } else {
                     subCursor = mProvider.query(Reminders.CONTENT_URI, REMINDERS_PROJECTION,
-                            "event_id=" + eventId, null, null);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) }  /* selectionArgs */,
+                            null /* sortOrder */);
                 }
                 try {
                     while (subCursor.moveToNext()) {
@@ -721,10 +725,14 @@
 
                 if (mResolver != null) {
                     subCursor = mResolver.query(Attendees.CONTENT_URI, ATTENDEES_PROJECTION,
-                            "event_id=" + eventId, null /* selectionArgs */, null /* sortOrder */);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) } /* selectionArgs */,
+                            null /* sortOrder */);
                 } else {
                     subCursor = mProvider.query(Attendees.CONTENT_URI, ATTENDEES_PROJECTION,
-                            "event_id=" + eventId, null /* selectionArgs */, null /* sortOrder */);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) } /* selectionArgs */,
+                            null /* sortOrder */);
                 }
                 try {
                     while (subCursor.moveToNext()) {
@@ -747,10 +755,14 @@
 
                 if (mResolver != null) {
                     subCursor = mResolver.query(ExtendedProperties.CONTENT_URI, EXTENDED_PROJECTION,
-                            "event_id=" + eventId, null /* selectionArgs */, null /* sortOrder */);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) } /* selectionArgs */,
+                            null /* sortOrder */);
                 } else {
                     subCursor = mProvider.query(ExtendedProperties.CONTENT_URI, EXTENDED_PROJECTION,
-                            "event_id=" + eventId, null /* selectionArgs */, null /* sortOrder */);
+                            WHERE_EVENT_ID,
+                            new String[] { Long.toString(eventId) } /* selectionArgs */,
+                            null /* sortOrder */);
                 }
                 try {
                     while (subCursor.moveToNext()) {
@@ -827,12 +839,14 @@
      */
     public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns {
 
+        private static final String WHERE_CALENDARS_SELECTED = Calendars.SELECTED + "=1";
+
         public static final Cursor query(ContentResolver cr, String[] projection,
                                          long begin, long end) {
             Uri.Builder builder = CONTENT_URI.buildUpon();
             ContentUris.appendId(builder, begin);
             ContentUris.appendId(builder, end);
-            return cr.query(builder.build(), projection, Calendars.SELECTED + "=1",
+            return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED,
                          null, DEFAULT_SORT_ORDER);
         }
 
@@ -842,9 +856,9 @@
             ContentUris.appendId(builder, begin);
             ContentUris.appendId(builder, end);
             if (TextUtils.isEmpty(where)) {
-                where = Calendars.SELECTED + "=1";
+                where = WHERE_CALENDARS_SELECTED;
             } else {
-                where = "(" + where + ") AND " + Calendars.SELECTED + "=1";
+                where = "(" + where + ") AND " + WHERE_CALENDARS_SELECTED;
             }
             return cr.query(builder.build(), projection, where,
                          null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
@@ -976,7 +990,7 @@
                 "/instances/groupbyday");
 
         public static final String[] PROJECTION = { STARTDAY, ENDDAY };
-        public static final String SELECTION = "selected==1";
+        public static final String SELECTION = "selected=1";
 
         /**
          * Retrieves the days with events for the Julian days starting at "startDay"
@@ -1107,10 +1121,23 @@
 
     public static final class CalendarAlerts implements BaseColumns,
             CalendarAlertsColumns, EventsColumns, CalendarsColumns {
+
         public static final String TABLE_NAME = "CalendarAlerts";
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY +
                 "/calendar_alerts");
 
+        private static final String WHERE_ALARM_EXISTS = EVENT_ID + "=?"
+                + " AND " + BEGIN + "=?"
+                + " AND " + ALARM_TIME + "=?";
+
+        private static final String WHERE_FINDNEXTALARMTIME = ALARM_TIME + ">=?";
+        private static final String SORT_ORDER_ALARMTIME_ASC = ALARM_TIME + " ASC";
+
+        private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + SCHEDULED
+                + " AND " + ALARM_TIME + "<?"
+                + " AND " + ALARM_TIME + ">?"
+                + " AND " + END + ">=?";
+
         /**
          * This URI is for grouping the query results by event_id and begin
          * time.  This will return one result per instance of an event.  So
@@ -1158,7 +1185,12 @@
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
             String[] projection = new String[] { ALARM_TIME };
-            Cursor cursor = query(cr, projection, selection, null, ALARM_TIME + " ASC");
+            Cursor cursor = query(cr, projection,
+                    WHERE_FINDNEXTALARMTIME,
+                    new String[] {
+                        Long.toString(millis)
+                    },
+                    SORT_ORDER_ALARMTIME_ASC);
             long alarmTime = -1;
             try {
                 if (cursor != null && cursor.moveToFirst()) {
@@ -1188,17 +1220,21 @@
             // and should have fired by now and are not too old.
             long now = System.currentTimeMillis();
             long ancient = now - DateUtils.DAY_IN_MILLIS;
-            String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.SCHEDULED
-                    + " AND " + CalendarAlerts.ALARM_TIME + "<" + now
-                    + " AND " + CalendarAlerts.ALARM_TIME + ">" + ancient
-                    + " AND " + CalendarAlerts.END + ">=" + now;
             String[] projection = new String[] {
                     ALARM_TIME,
             };
 
             // TODO: construct an explicit SQL query so that we can add
             // "GROUPBY" instead of doing a sort and de-dup
-            Cursor cursor = CalendarAlerts.query(cr, projection, selection, null, "alarmTime ASC");
+            Cursor cursor = CalendarAlerts.query(cr,
+                    projection,
+                    WHERE_RESCHEDULE_MISSED_ALARMS,
+                    new String[] {
+                        Long.toString(now),
+                        Long.toString(ancient),
+                        Long.toString(now)
+                    },
+                    SORT_ORDER_ALARMTIME_ASC);
             if (cursor == null) {
                 return;
             }
@@ -1237,8 +1273,8 @@
                 manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
             }
 
-            Intent intent = new Intent(android.provider.Calendar.EVENT_REMINDER_ACTION);
-            intent.putExtra(android.provider.Calendar.CalendarAlerts.ALARM_TIME, alarmTime);
+            Intent intent = new Intent(EVENT_REMINDER_ACTION);
+            intent.putExtra(ALARM_TIME, alarmTime);
             PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
                     PendingIntent.FLAG_CANCEL_CURRENT);
             manager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
@@ -1258,13 +1294,18 @@
          */
         public static final boolean alarmExists(ContentResolver cr, long eventId,
                 long begin, long alarmTime) {
-            String selection = CalendarAlerts.EVENT_ID + "=" + eventId
-                    + " AND " + CalendarAlerts.BEGIN + "=" + begin
-                    + " AND " + CalendarAlerts.ALARM_TIME + "=" + alarmTime;
             // TODO: construct an explicit SQL query so that we can add
             // "LIMIT 1" to the end and get just one result.
-            String[] projection = new String[] { CalendarAlerts.ALARM_TIME };
-            Cursor cursor = query(cr, projection, selection, null, null);
+            String[] projection = new String[] { ALARM_TIME };
+            Cursor cursor = query(cr,
+                    projection,
+                    WHERE_ALARM_EXISTS,
+                    new String[] {
+                        Long.toString(eventId),
+                        Long.toString(begin),
+                        Long.toString(alarmTime)
+                    },
+                    null);
             boolean found = false;
             try {
                 if (cursor != null && cursor.getCount() > 0) {
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 2b78d2d..acdfc28 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -105,7 +105,7 @@
      * Distance a touch can wander before we think the user is attempting a paged scroll
      * (in dips)
      */
-    private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 3;
+    private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
     
     /**
      * Distance between the first touch and second touch to still be considered a double tap
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f5e2f1d..06e9bbf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1748,9 +1748,9 @@
              The default value is true. -->
         <attr name="footerDividersEnabled" format="boolean" />
         <!-- Drawable to draw above list content. -->
-        <attr name="overscrollHeader" format="reference" />
+        <attr name="overscrollHeader" format="reference|color" />
         <!-- Drawable to draw below list content. -->
-        <attr name="overscrollFooter" format="reference" />
+        <attr name="overscrollFooter" format="reference|color" />
     </declare-styleable>
     <declare-styleable name="MenuView">
         <!-- Default appearance of menu item text. -->
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index 98ebc48..23522bd 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -50,7 +50,7 @@
 
 private:
     enum {
-        kBufferSize = 64 * 1024
+        kBufferSize = 32 * 1024
     };
 
     String8 mHeaders;
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index f623295b..c6bbbcc 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -159,8 +159,10 @@
 status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
 {
     Mutex::Autolock _l(mLock);
-    if ((mPlayer != NULL) && ( mCurrentState & MEDIA_PLAYER_INITIALIZED ))
-    {
+    const bool hasBeenInitialized =
+            (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
+            ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
+    if ((mPlayer != NULL) && hasBeenInitialized) {
          LOGV("invoke %d", request.dataSize());
          return  mPlayer->invoke(request, reply);
     }
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 1696eb96..8468a07 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -102,7 +102,7 @@
         source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)) {
         source = new HTTPDataSource(uri, headers);
-        source = new CachingDataSource(source, 64 * 1024, 10);
+        source = new CachingDataSource(source, 32 * 1024, 20);
     } else {
         // Assume it's a filename.
         source = new FileSource(uri);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index df6235f..c0cf97c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -20,7 +20,6 @@
 
 #include "include/StagefrightMetadataRetriever.h"
 
-#include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
diff --git a/tests/DumpRenderTree/assets/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py
index d3726c1..b6e7bf3 100755
--- a/tests/DumpRenderTree/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree/assets/run_layout_tests.py
@@ -246,6 +246,7 @@
 
   result_files = ["/sdcard/layout_tests_passed.txt",
                   "/sdcard/layout_tests_failed.txt",
+                  "/sdcard/layout_tests_ignored.txt",
                   "/sdcard/layout_tests_nontext.txt"]
   for file in result_files:
     shell_cmd_str = adb_cmd + " pull " + file + " " + results_dir
@@ -263,10 +264,13 @@
   logging.info(str(passed_tests) + " passed")
   failed_tests = CountLineNumber(results_dir + "/layout_tests_failed.txt")
   logging.info(str(failed_tests) + " failed")
+  ignored_tests = CountLineNumber(results_dir + "/layout_tests_ignored.txt")
+  logging.info(str(ignored_tests) + " ignored results")
   crashed_tests = CountLineNumber(results_dir + "/layout_tests_crashed.txt")
   logging.info(str(crashed_tests) + " crashed")
   nontext_tests = CountLineNumber(results_dir + "/layout_tests_nontext.txt")
   logging.info(str(nontext_tests) + " no dumpAsText")
+  logging.info(str(passed_tests + failed_tests + ignored_tests + crashed_tests + nontext_tests) + " TOTAL")
 
   logging.info("Results are stored under: " + results_dir + "\n")
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 77adac6..eecd00a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -23,27 +23,33 @@
 
     private static final String LOGTAG = "FileFilter";
 
+    // Returns whether we should ignore this test and skip running it.
+    // Currently we use this only for tests that crash the browser.
+    // TODO: Once these crashes are fixed, we should probably eliminate this
+    // method, as no test should crash.
     public static boolean ignoreTest(String file) {
-        // treat files like directories for the time being.
-        for (int i = 0; i < ignoreTestList.length; i ++) {
+        for (int i = 0; i < ignoreTestList.length; i++) {
             if (file.endsWith(ignoreTestList[i])) {
                 Log.v(LOGTAG, "File path in list of ignored tests: " + file);
                 return true;
             }
         }
-        for (int i = 0; i < ignoreTestDirs.length; i++) {
-            if (file.endsWith(ignoreTestDirs[i])) {
-                Log.v(LOGTAG, "File path in list of ignored directories: " + file);
+        return false;
+    }
+
+    // Returns whether a directory does not contain layout tests and so can be
+    // ignored.
+    public static boolean isNonTestDir(String file) {
+        for (int i = 0; i < nonTestDirs.length; i++) {
+            if (file.endsWith(nonTestDirs[i])) {
                 return true;
             }
         }
-        // We should run tests for which the expected result is wrong, as there is
-        // value in checking that they don't cause crashes.
-        // TODO: Run these tests but ignore the result.
-        return ignoreResults(file);
+        return false;
     }
 
-    public static boolean ignoreResults(String file) {
+    // Returns whether we should ignore the result of this test.
+    public static boolean ignoreResult(String file) {
         for (int i = 0; i < ignoreResultList.size(); i++) {
             if (file.endsWith(ignoreResultList.get(i))) {
                 Log.v(LOGTAG, "File path in list of ignored results: " + file);
@@ -51,7 +57,7 @@
             }
         }
         return false;
-      }
+    }
 
     final static Vector<String> ignoreResultList = new Vector<String>();
 
@@ -59,21 +65,16 @@
         fillIgnoreResultList();
     }
 
-    static final String[] ignoreTestDirs = {
+    static final String[] nonTestDirs = {
         ".", // ignore hidden directories and files
         "resources", // ignore resource directories
         ".svn", // don't run anything under .svn folder
-        "profiler",  // profiler is not supported
-        "svg",  // svg is not supported
-        "platform",  // platform specific
+        "platform"  // No-Android specific tests
     };
 
-    static final String [] ignoreTestList = {
-        "editing/selection/move-left-right.html",
+    static final String[] ignoreTestList = {
         "fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
-        "storage/domstorage/localstorage/private-browsing-affects-storage.html", // No notion of private browsing.
-        "storage/domstorage/sessionstorage/private-browsing-affects-storage.html", // No notion of private browsing.
-        "storage/private-browsing-readonly.html", // No notion of private browsing.
+        "editing/selection/move-left-right.html" // Causes DumpRenderTree to hang
     };
 
     static void fillIgnoreResultList() {
@@ -113,6 +114,7 @@
         ignoreResultList.add("fast/workers/shared-worker-shared.html"); // shared workers not supported
         ignoreResultList.add("fast/workers/shared-worker-simple.html"); // shared workers not supported
 
+        // TODO: These need to be triaged
         ignoreResultList.add("fast/css/case-transform.html"); // will not fix #619707
         ignoreResultList.add("fast/dom/Element/offsetLeft-offsetTop-body-quirk.html"); // different screen size result in extra spaces in Apple compared to us
         ignoreResultList.add("fast/dom/Window/Plug-ins.html"); // need test plugin
@@ -183,6 +185,12 @@
         ignoreResultList.add("fast/parser/script-tag-with-trailing-slash.html"); // not capturing the console messages
         ignoreResultList.add("fast/replaced/image-map.html"); // requires eventSender.mouseDown(),mouseUp()
         ignoreResultList.add("fast/text/plain-text-line-breaks.html"); // extra spacing because iFrames rendered next to each other on Apple
+        ignoreResultList.add("profiler"); // profiler is not supported
+        ignoreResultList.add("storage/domstorage/localstorage/private-browsing-affects-storage.html"); // No notion of private browsing.
+        ignoreResultList.add("storage/domstorage/sessionstorage/private-browsing-affects-storage.html"); // No notion of private browsing.
+        ignoreResultList.add("storage/private-browsing-readonly.html"); // No notion of private browsing.
+        ignoreResultList.add("svg"); // svg is not supported
+
     }
 
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index ef0c6c6..322b0d2 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -43,38 +43,45 @@
     }
 
     public static void findLayoutTestsRecursively(BufferedOutputStream bos,
-            String dir) throws IOException {
+            String dir, boolean ignoreResultsInDir) throws IOException {
         Log.v(LOGTAG, "Searching tests under " + dir);
 
         File d = new File(dir);
         if (!d.isDirectory()) {
             throw new AssertionError("A directory expected, but got " + dir);
         }
+        ignoreResultsInDir |= FileFilter.ignoreResult(dir);
 
         String[] files = d.list();
         for (int i = 0; i < files.length; i++) {
             String s = dir + "/" + files[i];
-            if (s.endsWith("TEMPLATE.html")) {
-                continue;
-            }
-            if (FileFilter.ignoreTest(s)) {
-                Log.v(LOGTAG, "  Ignoring: " + s);
-                continue;
-            }
-            if (s.toLowerCase().endsWith(".html")
-                    || s.toLowerCase().endsWith(".xml")) {
-                bos.write(s.getBytes());
-                bos.write('\n');
-                continue;
-            }
 
             File f = new File(s);
             if (f.isDirectory()) {
-                findLayoutTestsRecursively(bos, s);
+                // If this is not a test directory, we don't recurse into it.
+                if (!FileFilter.isNonTestDir(s)) {
+                    Log.v(LOGTAG, "Recursing on " + s);
+                    findLayoutTestsRecursively(bos, s, ignoreResultsInDir);
+                }
                 continue;
             }
 
-            Log.v(LOGTAG, "Skipping " + s);
+            // If this test should be ignored, we skip it completely.
+            if (FileFilter.ignoreTest(s)) {
+                Log.v(LOGTAG, "Ignoring: " + s);
+                continue;
+            }
+
+            if ((s.toLowerCase().endsWith(".html") || s.toLowerCase().endsWith(".xml"))
+                    && !s.endsWith("TEMPLATE.html")) {
+                Log.v(LOGTAG, "Recording " + s);
+                bos.write(s.getBytes());
+                // If the result of this test should be ignored, we still run the test.
+                if (ignoreResultsInDir || FileFilter.ignoreResult(s)) {
+                    bos.write((" IGNORE_RESULT").getBytes());
+                }
+                bos.write('\n');
+            }
         }
     }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index ac6933fc..042158a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -38,14 +38,16 @@
 import java.io.OutputStream;
 import java.util.Vector;
 
-// TestRecorder creates three files ...
+// TestRecorder creates four files ...
 // - passing tests
 // - failing tests
+// - tests for which results are ignored
 // - tests with no text results available
 // TestRecorder does not have the ability to clear the results.
 class MyTestRecorder {
     private BufferedOutputStream mBufferedOutputPassedStream;
     private BufferedOutputStream mBufferedOutputFailedStream;
+    private BufferedOutputStream mBufferedOutputIgnoreResultStream;
     private BufferedOutputStream mBufferedOutputNoResultStream;
 
     public void passed(String layout_file) {
@@ -68,6 +70,16 @@
         }
     }
 
+    public void ignoreResult(String layout_file) {
+        try {
+            mBufferedOutputIgnoreResultStream.write(layout_file.getBytes());
+            mBufferedOutputIgnoreResultStream.write('\n');
+            mBufferedOutputIgnoreResultStream.flush();
+        } catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+
     public void noResult(String layout_file) {
         try {
             mBufferedOutputNoResultStream.write(layout_file.getBytes());
@@ -82,12 +94,15 @@
         try {
             File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt");
             File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt");
+            File resultsIgnoreResultFile = new File("/sdcard/layout_tests_ignored.txt");
             File noExpectedResultFile = new File("/sdcard/layout_tests_nontext.txt");
 
             mBufferedOutputPassedStream =
                 new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume));
             mBufferedOutputFailedStream =
                 new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume));
+            mBufferedOutputIgnoreResultStream =
+                new BufferedOutputStream(new FileOutputStream(resultsIgnoreResultFile, resume));
             mBufferedOutputNoResultStream =
                 new BufferedOutputStream(new FileOutputStream(noExpectedResultFile, resume));
         } catch (Exception e) {
@@ -99,6 +114,7 @@
         try {
             mBufferedOutputPassedStream.close();
             mBufferedOutputFailedStream.close();
+            mBufferedOutputIgnoreResultStream.close();
             mBufferedOutputNoResultStream.close();
         } catch (Exception e) {
             e.printStackTrace();
@@ -132,6 +148,8 @@
 
     private MyTestRecorder mResultRecorder;
     private Vector<String> mTestList;
+    // Whether we should ignore the result for the corresponding test. Ordered same as mTestList.
+    private Vector<Boolean> mTestListIgnoreResult;
     private boolean mRebaselineResults;
     // The JavaScript engine currently in use. This determines which set of Android-specific
     // expected test results we use.
@@ -158,8 +176,11 @@
             BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE));
             String line = inReader.readLine();
             while (line != null) {
-                if (line.startsWith(mTestPathPrefix))
-                    mTestList.add(line);
+                if (line.startsWith(mTestPathPrefix)) {
+                    String[] components = line.split(" ");
+                    mTestList.add(components[0]);
+                    mTestListIgnoreResult.add(components.length > 1 && components[1].equals("IGNORE_RESULT"));
+                }
                 line = inReader.readLine();
             }
             inReader.close();
@@ -176,6 +197,7 @@
             for (int i = 0; i < mTestList.size(); i++) {
                 if (mTestList.elementAt(i).equals(line)) {
                     mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size()));
+                    mTestListIgnoreResult = new Vector<Boolean>(mTestListIgnoreResult.subList(i+1, mTestListIgnoreResult.size()));
                     break;
                 }
             }
@@ -236,14 +258,24 @@
         mResultRecorder.passed(file);
     }
 
+    private void ignoreResultCase(String file) {
+        Log.v("Layout test:", file + " ignore result");
+        mResultRecorder.ignoreResult(file);
+    }
+
     private void noResultCase(String file) {
         Log.v("Layout test:", file + " no expected result");
         mResultRecorder.noResult(file);
     }
 
-    private void processResult(String testFile, String actualResultFile, String expectedResultFile) {
+    private void processResult(String testFile, String actualResultFile, String expectedResultFile, boolean ignoreResult) {
         Log.v(LOGTAG, "  Processing result: " + testFile);
 
+        if (ignoreResult) {
+            ignoreResultCase(testFile);
+            return;
+        }
+
         File actual = new File(actualResultFile);
         File expected = new File(expectedResultFile);
         if (actual.exists() && expected.exists()) {
@@ -266,7 +298,7 @@
         }
     }
 
-    private void runTestAndWaitUntilDone(TestShellActivity activity, String test, int timeout) {
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String test, int timeout, boolean ignoreResult) {
         activity.setCallback(new TestShellCallback() {
             public void finished() {
                 synchronized (LayoutTestsAutoTest.this) {
@@ -320,7 +352,7 @@
                 expectedResultFile = getAndroidExpectedResultFile(expectedResultFile);
             }
 
-            processResult(test, resultFile, expectedResultFile);
+            processResult(test, resultFile, expectedResultFile, ignoreResult);
         }
     }
 
@@ -336,6 +368,7 @@
         }
 
         this.mTestList = new Vector<String>();
+        this.mTestListIgnoreResult = new Vector<Boolean>();
 
         // Read settings
         mTestPathPrefix = (new File(LAYOUT_TESTS_ROOT + runner.mTestPath)).getAbsolutePath();
@@ -372,9 +405,10 @@
         }
         for (int i = 0; i < mTestList.size(); i++) {
             String s = mTestList.elementAt(i);
+            boolean ignoreResult = mTestListIgnoreResult.elementAt(i);
             FsUtils.updateTestStatus(TEST_STATUS_FILE, s);
             // Run tests
-            runTestAndWaitUntilDone(activity, s, runner.mTimeoutInMillis);
+            runTestAndWaitUntilDone(activity, s, runner.mTimeoutInMillis, ignoreResult);
         }
 
         FsUtils.updateTestStatus(TEST_STATUS_FILE, "#DONE");
@@ -399,7 +433,7 @@
         try {
             File tests_list = new File(LAYOUT_TESTS_LIST_FILE);
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tests_list, false));
-            FsUtils.findLayoutTestsRecursively(bos, getTestPath());
+            FsUtils.findLayoutTestsRecursively(bos, getTestPath(), false); // Don't ignore results
             bos.flush();
             bos.close();
        } catch (Exception e) {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
index e15ab65..82671eb 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
@@ -68,7 +68,7 @@
         try {
             File tests_list = new File(LAYOUT_TESTS_LIST_FILE);
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tests_list, false));
-            FsUtils.findLayoutTestsRecursively(bos, path);
+            FsUtils.findLayoutTestsRecursively(bos, path, false); // Don't ignore results
             bos.flush();
             bos.close();
        } catch (Exception e) {
@@ -77,4 +77,3 @@
     }
 
 }
-