Merge change 25954 into eclair

* changes:
  Moving DISPLAY_NAME to column "data1" to keep it "aligned" with other data types.
diff --git a/cmds/keystore/Android.mk b/cmds/keystore/Android.mk
index 8804636..15a199f 100644
--- a/cmds/keystore/Android.mk
+++ b/cmds/keystore/Android.mk
@@ -1,22 +1,36 @@
+#
+# 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.
+#
+
 ifneq ($(TARGET_SIMULATOR),true)
 
 LOCAL_PATH:= $(call my-dir)
+
 include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    netkeystore.c netkeystore_main.c keymgmt.c
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, system-core)/cutils \
-    external/openssl/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils libssl
-
-LOCAL_STATIC_LIBRARIES :=
-
+LOCAL_SRC_FILES := keystore.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
 LOCAL_MODULE:= keystore
-
 include $(BUILD_EXECUTABLE)
 
-endif # !simulator))
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := keystore_cli.c
+LOCAL_C_INCLUDES := external/openssl/include
+LOCAL_SHARED_LIBRARIES := libcutils libcrypto
+LOCAL_MODULE:= keystore_cli
+LOCAL_MODULE_TAGS := debug
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
index 2bcba97..ec4e2a2 100644
--- a/cmds/keystore/keystore.c
+++ b/cmds/keystore/keystore.c
@@ -125,6 +125,12 @@
     return length;
 }
 
+static int recv_end_of_file()
+{
+    uint8_t byte;
+    return recv(the_socket, &byte, 1, 0) == 0;
+}
+
 static void send_code(int8_t code)
 {
     send(the_socket, &code, 1, 0);
@@ -217,8 +223,10 @@
 /* Here are the actions. Each of them is a function without arguments. All
  * information is defined in global variables, which are set properly before
  * performing an action. The number of parameters required by each action is
- * fixed and defined in a table. Note that the lengths of parameters are checked
- * when they are received, so boundary checks on parameters are omitted. */
+ * fixed and defined in a table. If the return value of an action is positive,
+ * it will be treated as a response code and transmitted to the client. Note
+ * that the lengths of parameters are checked when they are received, so
+ * boundary checks on parameters are omitted. */
 
 #define MAX_PARAM   2
 #define MAX_RETRY   4
@@ -321,12 +329,10 @@
         return SYSTEM_ERROR;
     }
     while ((file = readdir(dir)) != NULL) {
-        if (strcmp(".", file->d_name) || strcmp("..", file->d_name)) {
-            unlink(file->d_name);
-        }
+        unlink(file->d_name);
     }
     closedir(dir);
-    return UNINITIALIZED;
+    return NO_ERROR;
 }
 
 #define MASTER_KEY_FILE ".masterkey"
@@ -358,7 +364,8 @@
         }
         if (n != NO_ERROR || blob.length != MASTER_KEY_SIZE) {
             if (retry <= 0) {
-                return reset();
+                reset();
+                return UNINITIALIZED;
             }
             return WRONG_PASSWORD + --retry;
         }
@@ -387,7 +394,7 @@
     memset(&encryption_key, 0, sizeof(encryption_key));
     memset(&decryption_key, 0, sizeof(decryption_key));
     state = LOCKED;
-    return LOCKED;
+    return NO_ERROR;
 }
 
 static int8_t unlock()
@@ -421,9 +428,9 @@
     {test,     't', 0,        TEST,     {0}},
     {get,      'g', NO_ERROR, GET,      {KEY_SIZE}},
     {insert,   'i', NO_ERROR, INSERT,   {KEY_SIZE, VALUE_SIZE}},
-    {delete,   'd', NO_ERROR, DELETE,   {KEY_SIZE}},
-    {exist,    'e', NO_ERROR, EXIST,    {KEY_SIZE}},
-    {scan,     's', NO_ERROR, SCAN,     {KEY_SIZE}},
+    {delete,   'd', 0,        DELETE,   {KEY_SIZE}},
+    {exist,    'e', 0,        EXIST,    {KEY_SIZE}},
+    {scan,     's', 0,        SCAN,     {KEY_SIZE}},
     {reset,    'r', 0,        RESET,    {0}},
     {password, 'p', 0,        PASSWORD, {PASSWORD_SIZE, PASSWORD_SIZE}},
     {lock,     'l', NO_ERROR, LOCK,     {0}},
@@ -471,6 +478,9 @@
             return PROTOCOL_ERROR;
         }
     }
+    if (!recv_end_of_file()) {
+        return PROTOCOL_ERROR;
+    }
     return action->run();
 }
 
diff --git a/cmds/keystore/keystore_cli.c b/cmds/keystore/keystore_cli.c
index b0b76ff..e8afb5a 100644
--- a/cmds/keystore/keystore_cli.c
+++ b/cmds/keystore/keystore_cli.c
@@ -53,8 +53,8 @@
         return 0;
     }
 
-    sock = socket_local_client("keystore",
-            ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+    sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+                               SOCK_STREAM);
     if (sock == -1) {
         puts("Failed to connect");
         return 1;
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 7665e81..0e7e1ae 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -1,53 +1,69 @@
 /*
-**
-** Copyright 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.
-*/
+ * 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.
+ */
 
 #ifndef __KEYSTORE_GET_H__
 #define __KEYSTORE_GET_H__
 
 #include <stdio.h>
-#include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
-#include "certtool.h"
+#include <cutils/sockets.h>
 
-/* This function is provided to native components to get values from keystore.
- * Users are required to link against libcutils. If something goes wrong, NULL
- * is returned. Otherwise it returns the value in dynamically allocated memory
- * and sets the size if the pointer is not NULL. One can release the memory by
- * calling free(). */
-static char *keystore_get(const char *key, int *size)
+#define KEYSTORE_MESSAGE_SIZE 65535
+
+/* This function is provided for native components to get values from keystore.
+ * Users are required to link against libcutils. The lengths of keys and values
+ * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
+ * the requested value or -1 if something goes wrong. */
+static int keystore_get(const char *key, char *value)
 {
-    char buffer[MAX_KEY_VALUE_LENGTH];
-    char *value;
-    int length;
+    int length = strlen(key);
+    uint8_t bytes[2] = {length >> 8, length};
+    uint8_t code = 'g';
+    int sock;
 
-    if (get_cert(key, (unsigned char *)buffer, &length) != 0) {
-        return NULL;
+    if (length > KEYSTORE_MESSAGE_SIZE) {
+        return -1;
     }
-    value = malloc(length + 1);
-    if (!value) {
-        return NULL;
+    sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED,
+                               SOCK_STREAM);
+    if (sock == -1) {
+        return -1;
     }
-    memcpy(value, buffer, length);
-    value[length] = 0;
-    if (size) {
-        *size = length;
+    if (send(sock, &code, 1, 0) == 1 && send(sock, bytes, 2, 0) == 2 &&
+        send(sock, key, length, 0) == length && shutdown(sock, SHUT_WR) == 0 &&
+        recv(sock, &code, 1, 0) == 1 && code == /* NO_ERROR */ 1 &&
+        recv(sock, &bytes[0], 1, 0) == 1 && recv(sock, &bytes[1], 1, 0) == 1) {
+        int offset = 0;
+        length = bytes[0] << 8 | bytes[1];
+        while (offset < length) {
+            int n = recv(sock, &value[offset], length - offset, 0);
+            if (n <= 0) {
+                length = -1;
+                break;
+            }
+            offset += n;
+        }
     }
-    return value;
+    close(sock);
+    return length;
 }
 
 #endif
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index d05c9ab..caf72af 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -736,7 +736,8 @@
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+        if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
+            event.startTracking();
             // Consume search key for later use.
             return true;
         }
@@ -1181,7 +1182,7 @@
             // report back about the click
             if (mGlobalSearchMode) {
                 // in global search mode, do it via cursor
-                mSuggestionsAdapter.callCursorOnClick(c, position);
+                mSuggestionsAdapter.callCursorOnClick(c, position, actionKey, actionMsg);
             } else if (intent != null
                     && mPreviousComponents != null
                     && !mPreviousComponents.isEmpty()) {
@@ -1218,7 +1219,7 @@
         cv.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION, intent.getAction());
         cv.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, intent.getDataString());
         cv.put(SearchManager.SUGGEST_COLUMN_INTENT_COMPONENT_NAME,
-                        intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY));
+                intent.getComponent().flattenToShortString());
 
         // ensure the icons will work for global search
         cv.put(SearchManager.SUGGEST_COLUMN_ICON_1,
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 3a14f6f..6a0285d 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1343,6 +1343,10 @@
                 = "DialogCursorProtocol.CLICK.sendPosition";
         public final static String CLICK_SEND_MAX_DISPLAY_POS
                 = "DialogCursorProtocol.CLICK.sendDisplayPosition";
+        public final static String CLICK_SEND_ACTION_KEY
+                = "DialogCursorProtocol.CLICK.sendActionKey";
+        public final static String CLICK_SEND_ACTION_MSG
+                = "DialogCursorProtocol.CLICK.sendActionMsg";
         public final static String CLICK_RECEIVE_SELECTED_POS
                 = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
 
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 4f9531e..9234a9c 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -26,7 +26,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
@@ -37,6 +36,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Filter;
@@ -47,7 +47,6 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
 import java.util.WeakHashMap;
 
 /**
@@ -290,12 +289,16 @@
      * @param cursor The cursor
      * @param position The position that was clicked.
      */
-    void callCursorOnClick(Cursor cursor, int position) {
+    void callCursorOnClick(Cursor cursor, int position, int actionKey, String actionMsg) {
         if (!mGlobalSearchMode) return;
-        final Bundle request = new Bundle(3);
+        final Bundle request = new Bundle(5);
         request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
         request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
         request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+        if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
+            request.putInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, actionKey);
+            request.putString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG, actionMsg);
+        }
         final Bundle response = cursor.respond(request);
         mMaxDisplayed = -1;
         mListItemToSelect = response.getInt(
@@ -569,69 +572,91 @@
         if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
             return null;
         }
-
-        // First, check the cache.
-        Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId);
-        if (cached != null) {
-            if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId);
-            return cached.newDrawable(mProviderContext.getResources());
-        }
-
-        Drawable drawable = null;
         try {
-            // Not cached, try using it as a plain resource ID in the provider's context.
+            // First, see if it's just an integer
             int resourceId = Integer.parseInt(drawableId);
+            // It's an int, look for it in the cache
+            String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE
+                    + "://" + mProviderContext.getPackageName() + "/" + resourceId;
+            // Must use URI as cache key, since ints are app-specific
+            Drawable drawable = checkIconCache(drawableUri);
+            if (drawable != null) {
+                return drawable;
+            }
+            // Not cached, find it by resource ID
             drawable = mProviderContext.getResources().getDrawable(resourceId);
+            // Stick it in the cache, using the URI as key
+            storeInIconCache(drawableUri, drawable);
+            return drawable;
         } catch (NumberFormatException nfe) {
-            // The id was not an integer resource id, use it as a URI
-            try {
-                Uri uri = Uri.parse(drawableId);
-                String scheme = uri.getScheme();
-                if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
-                    // Load drawables through Resources, to get the source density information
-                    OpenResourceIdResult r =
-                            mProviderContext.getContentResolver().getResourceId(uri);
+            // It's not an integer, use it as a URI
+            Drawable drawable = checkIconCache(drawableId);
+            if (drawable != null) {
+                return drawable;
+            }
+            Uri uri = Uri.parse(drawableId);
+            drawable = getDrawable(uri);
+            storeInIconCache(drawableId, drawable);
+            return drawable;
+        } catch (Resources.NotFoundException nfe) {
+            // It was an integer, but it couldn't be found, bail out
+            Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
+            return null;
+        }
+    }
+
+    /**
+     * Gets a drawable by URI, without using the cache.
+     *
+     * @return A drawable, or {@code null} if the drawable could not be loaded.
+     */
+    private Drawable getDrawable(Uri uri) {
+        try {
+            String scheme = uri.getScheme();
+            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+                // Load drawables through Resources, to get the source density information
+                OpenResourceIdResult r =
+                    mProviderContext.getContentResolver().getResourceId(uri);
+                try {
+                    return r.r.getDrawable(r.id);
+                } catch (Resources.NotFoundException ex) {
+                    throw new FileNotFoundException("Resource does not exist: " + uri);
+                }
+            } else {
+                // Let the ContentResolver handle content and file URIs.
+                InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+                if (stream == null) {
+                    throw new FileNotFoundException("Failed to open " + uri);
+                }
+                try {
+                    return Drawable.createFromStream(stream, null);
+                } finally {
                     try {
-                        drawable = r.r.getDrawable(r.id);
-                    } catch (Resources.NotFoundException ex) {
-                        throw new FileNotFoundException("Resource does not exist: " + uri);
-                    }
-                } else {
-                    // Let the ContentResolver handle content and file URIs.
-                    InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
-                    if (stream == null) {
-                        throw new FileNotFoundException("Failed to open " + uri);
-                    }
-                    try {
-                        drawable = Drawable.createFromStream(stream, null);
-                    } finally {
-                        try {
-                            stream.close();
-                        } catch (IOException ex) {
-                            Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
-                        }
+                        stream.close();
+                    } catch (IOException ex) {
+                        Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
                     }
                 }
-            } catch (FileNotFoundException fnfe) {
-                Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
-                // drawable = null;
             }
-        } catch (Resources.NotFoundException nfe) {
-            Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
-            // drawable = null;
+        } catch (FileNotFoundException fnfe) {
+            Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage());
+            return null;
         }
+    }
 
-        if (drawable == null) {
-            if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
-        } else {
-            if (DBG) {
-                Log.d(LOG_TAG, "Found icon: " + drawableId);
-            }
-            // Cache it so we don't do this lookup again
-            mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+    private Drawable checkIconCache(String resourceUri) {
+        Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
+        if (cached == null) {
+            return null;
         }
+        if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
+        return cached.newDrawable();
+    }
 
-        return drawable;
+    private void storeInIconCache(String resourceUri, Drawable drawable) {
+        if (drawable != null) {
+            mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState());
+        }
     }
 
     /**
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 7859d5a..80613d8 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -514,7 +514,7 @@
     public SyncStorageEngine getSyncStorageEngine() {
         return mSyncStorageEngine;
     }
-    
+
     private void ensureAlarmService() {
         if (mAlarmService == null) {
             mAlarmService = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
@@ -1125,7 +1125,7 @@
         tobj.set(time);
         return tobj.format("%Y-%m-%d %H:%M:%S");
     }
-    
+
     protected void dumpSyncState(PrintWriter pw, StringBuilder sb) {
         pw.print("sync enabled: "); pw.println(isSyncEnabled());
         pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
@@ -1219,13 +1219,13 @@
                         = mSyncStorageEngine.getAuthority(status.authorityId);
                 if (authority != null) {
                     Account curAccount = authority.account;
-                    
+
                     if (processedAccounts.contains(curAccount)) {
                         continue;
                     }
-                    
+
                     processedAccounts.add(curAccount);
-                    
+
                     pw.print("  Account "); pw.print(authority.account.name);
                             pw.print(" "); pw.print(authority.account.type);
                             pw.println(":");
@@ -1271,7 +1271,7 @@
         pw.print(time/1000); pw.print('.'); pw.print((time/100)%10);
         pw.print('s');
     }
-    
+
     private void dumpDayStatistic(PrintWriter pw, SyncStorageEngine.DayStats ds) {
         pw.print("Success ("); pw.print(ds.successCount);
         if (ds.successCount > 0) {
@@ -1285,7 +1285,7 @@
         }
         pw.println(")");
     }
-    
+
     protected void dumpSyncHistory(PrintWriter pw, StringBuilder sb) {
         SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics();
         if (dses != null && dses[0] != null) {
@@ -1295,18 +1295,18 @@
             int today = dses[0].day;
             int i;
             SyncStorageEngine.DayStats ds;
-            
+
             // Print each day in the current week.
             for (i=1; i<=6 && i < dses.length; i++) {
                 ds = dses[i];
                 if (ds == null) break;
                 int delta = today-ds.day;
                 if (delta > 6) break;
-                
+
                 pw.print("  Day-"); pw.print(delta); pw.print(":  ");
                 dumpDayStatistic(pw, ds);
             }
-            
+
             // Aggregate all following days into weeks and print totals.
             int weekDay = today;
             while (i < dses.length) {
@@ -1321,7 +1321,7 @@
                     int delta = weekDay-ds.day;
                     if (delta > 6) break;
                     i++;
-                    
+
                     if (aggr == null) {
                         aggr = new SyncStorageEngine.DayStats(weekDay);
                     }
@@ -1336,7 +1336,7 @@
                 }
             }
         }
-        
+
         ArrayList<SyncStorageEngine.SyncHistoryItem> items
                 = mSyncStorageEngine.getSyncHistory();
         if (items != null && items.size() > 0) {
@@ -2132,7 +2132,8 @@
             final long now = System.currentTimeMillis();
 
             EventLog.writeEvent(2720, syncOperation.authority,
-                    SyncStorageEngine.EVENT_START, source);
+                                SyncStorageEngine.EVENT_START, source,
+                                syncOperation.account.name.hashCode());
 
             return mSyncStorageEngine.insertStartSyncEvent(
                     syncOperation.account, syncOperation.authority, now, source);
@@ -2141,7 +2142,8 @@
         public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
                 int upstreamActivity, int downstreamActivity, long elapsedTime) {
             EventLog.writeEvent(2720, syncOperation.authority,
-                    SyncStorageEngine.EVENT_STOP, syncOperation.syncSource);
+                                SyncStorageEngine.EVENT_STOP, syncOperation.syncSource,
+                                syncOperation.account.name.hashCode());
 
             mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime, resultMessage,
                     downstreamActivity, upstreamActivity);
@@ -2173,7 +2175,7 @@
                 syncOperation.pendingOperation = op;
                 add(syncOperation, op);
             }
-            
+
             if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */);
         }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fb33561..2a92e05 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -420,6 +420,7 @@
     private static final int STD_SPEED = 480;  // pixels per second
     // time for the longest scroll animation
     private static final int MAX_DURATION = 750;   // milliseconds
+    private static final int SLIDE_TITLE_DURATION = 500;   // milliseconds
     private Scroller mScroller;
 
     private boolean mWrapContent;
@@ -2000,7 +2001,7 @@
         getGlobalVisibleRect(r, p);
         r.offset(-p.x, -p.y);
         if (mFindIsUp) {
-            r.bottom -= FIND_HEIGHT;
+            r.bottom -= mFindHeight;
         }
     }
 
@@ -2072,9 +2073,6 @@
         }
     }
 
-    // Make sure this stays in sync with the actual height of the FindDialog.
-    private static final int FIND_HEIGHT = 79;
-
     @Override
     protected int computeVerticalScrollRange() {
         if (mDrawHistory) {
@@ -2305,7 +2303,11 @@
      *              that were found.
      */
     public int findAll(String find) {
-        mFindIsUp = true;
+        if (mFindIsUp == false) {
+            recordNewContentSize(mContentWidth, mContentHeight + mFindHeight,
+                    false);
+            mFindIsUp = true;
+        }
         int result = nativeFindAll(find.toLowerCase(), find.toUpperCase());
         invalidate();
         return result;
@@ -2314,6 +2316,7 @@
     // Used to know whether the find dialog is open.  Affects whether
     // or not we draw the highlights for matches.
     private boolean mFindIsUp;
+    private int mFindHeight;
 
     /**
      * Return the first substring consisting of the address of a physical
@@ -2369,7 +2372,11 @@
      * Clear the highlighting surrounding text matches created by findAll.
      */
     public void clearMatches() {
-        mFindIsUp = false;
+        if (mFindIsUp) {
+            recordNewContentSize(mContentWidth, mContentHeight - mFindHeight,
+                    false);
+            mFindIsUp = false;
+        }
         nativeSetFindIsDown();
         // Now that the dialog has been removed, ensure that we scroll to a
         // location that is not beyond the end of the page.
@@ -2378,6 +2385,16 @@
     }
 
     /**
+     * @hide
+     */
+    public void setFindDialogHeight(int height) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "setFindDialogHeight height=" + height);
+        }
+        mFindHeight = height;
+    }
+
+    /**
      * Query the document to see if it contains any image references. The
      * message object will be dispatched with arg1 being set to 1 if images
      * were found and 0 if the document does not reference any images.
@@ -2419,7 +2436,6 @@
     private boolean pinScrollBy(int dx, int dy, boolean animate, int animationDuration) {
         return pinScrollTo(mScrollX + dx, mScrollY + dy, animate, animationDuration);
     }
-
     // helper to pin the scrollTo parameters (already in view coordinates)
     // returns true if the scroll was changed
     private boolean pinScrollTo(int x, int y, boolean animate, int animationDuration) {
@@ -2431,15 +2447,6 @@
         if ((dx | dy) == 0) {
             return false;
         }
-        // By this point we have added in the title bar's height.  If the site
-        // is trying to scroll to the top of the page, scroll it to the top
-        // of the WebView including showing the title bar.
-        // mobile sites prefer to scroll to (0, 1), thus the + 1 below
-        if (getVisibleTitleHeight() > 0 && x == 0
-                && y <= getTitleHeight() + 1) {
-            y = 0;
-            animate = false;
-        }
         if (animate) {
             //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
             mScroller.startScroll(mScrollX, mScrollY, dx, dy,
@@ -2502,6 +2509,17 @@
         int vy = contentToViewY(cy);
 //        Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
 //                      vx + " " + vy + "]");
+        // Some mobile sites attempt to scroll the title bar off the page by
+        // scrolling to (0,0) or (0,1).  If we are at the top left corner of the
+        // page, assume this is an attempt to scroll off the title bar, and
+        // animate the title bar off screen slowly enough that the user can see
+        // it.
+        if (cx == 0 && cy <= 1 && mScrollX == 0 && mScrollY == 0) {
+            pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
+            // Since we are animating, we have not yet reached the desired
+            // scroll position.  Do not return true to request another attempt
+            return false;
+        }
         pinScrollTo(vx, vy, false, 0);
         // If the request was to scroll to a negative coordinate, treat it as if
         // it was a request to scroll to 0
@@ -4867,7 +4885,8 @@
                     final boolean updateLayout = viewSize.x == mLastWidthSent
                             && viewSize.y == mLastHeightSent;
                     recordNewContentSize(draw.mWidthHeight.x,
-                            draw.mWidthHeight.y, updateLayout);
+                            draw.mWidthHeight.y
+                            + (mFindIsUp ? mFindHeight : 0), updateLayout);
                     if (DebugFlags.WEB_VIEW) {
                         Rect b = draw.mInvalRegion.getBounds();
                         Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 71c6ff5..89581e6 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1172,6 +1172,8 @@
   <public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
   <public type="style" name="Theme.WallpaperSettings" />
   <public type="style" name="Theme.Light.WallpaperSettings" />
+  <public type="style" name="TextAppearance.SearchResult.Title" />
+  <public type="style" name="TextAppearance.SearchResult.Subtitle" />
   
   <!-- Semi-transparent background that can be used when placing a dark
        themed UI on top of some arbitrary background (such as the
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 04402fd..b29e571 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -59,11 +59,7 @@
         <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Large.Inverse</item>
         <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Medium.Inverse</item>
         <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item>
-
-        <!-- @hide -->
         <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.SearchResult.Title</item>
-        
-        <!-- @hide -->
         <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.SearchResult.Subtitle</item>
         
         <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 28c2992..43042c0b 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -28,9 +28,12 @@
  */
 public class Credentials {
     private static final String LOGTAG = "Credentials";
-    private static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
-    private static final String INSTALL_ACTION = "android.credentials.INSTALL";
-    private static Credentials singleton;
+
+    public static final String UNLOCK_ACTION = "android.credentials.UNLOCK";
+
+    public static final String INSTALL_ACTION = "android.credentials.INSTALL";
+
+    public static final String SYSTEM_INSTALL_ACTION = "android.credentials.SYSTEM_INSTALL";
 
     /** Key prefix for CA certificates. */
     public static final String CA_CERTIFICATE = "CACERT_";
@@ -59,6 +62,8 @@
     /** Data type for PKCS12. */
     public static final String PKCS12 = "PKCS12";
 
+    private static Credentials singleton;
+
     public static Credentials getInstance() {
         if (singleton == null) {
             singleton = new Credentials();
@@ -95,4 +100,12 @@
             Log.w(LOGTAG, e.toString());
         }
     }
+
+    public void installFromSdCard(Context context) {
+        try {
+            context.startActivity(new Intent(INSTALL_ACTION));
+        } catch (ActivityNotFoundException e) {
+            Log.w(LOGTAG, e.toString());
+        }
+    }
 }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
new file mode 100644
index 0000000..b47e399
--- /dev/null
+++ b/keystore/java/android/security/KeyStore.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.net.LocalSocketAddress;
+import android.net.LocalSocket;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public class KeyStore {
+    public static int NO_ERROR = 1;
+    public static int LOCKED = 2;
+    public static int UNINITIALIZED = 3;
+    public static int SYSTEM_ERROR = 4;
+    public static int PROTOCOL_ERROR = 5;
+    public static int PERMISSION_DENIED = 6;
+    public static int KEY_NOT_FOUND = 7;
+    public static int VALUE_CORRUPTED = 8;
+    public static int UNDEFINED_ACTION = 9;
+    public static int WRONG_PASSWORD = 10;
+
+    private static final LocalSocketAddress sAddress = new LocalSocketAddress(
+            "keystore", LocalSocketAddress.Namespace.RESERVED);
+
+    private int mError = NO_ERROR;
+
+    private KeyStore() {}
+
+    public static KeyStore getInstance() {
+        return new KeyStore();
+    }
+
+    public int test() {
+        execute('t');
+        return mError;
+    }
+
+    public byte[] get(byte[] key) {
+        byte[][] values = execute('g', key);
+        return (values == null) ? null : values[0];
+    }
+
+    public String get(String key) {
+        byte[] value = get(key.getBytes());
+        return (value == null) ? null : new String(value);
+    }
+
+    public boolean put(byte[] key, byte[] value) {
+        execute('i', key, value);
+        return mError == NO_ERROR;
+    }
+
+    public boolean put(String key, String value) {
+        return put(key.getBytes(), value.getBytes());
+    }
+
+    public boolean delete(byte[] key) {
+        execute('d', key);
+        return mError == NO_ERROR;
+    }
+
+    public boolean delete(String key) {
+        return delete(key.getBytes());
+    }
+
+    public boolean contains(byte[] key) {
+        execute('e', key);
+        return mError == NO_ERROR;
+    }
+
+    public boolean contains(String key) {
+        return contains(key.getBytes());
+    }
+
+    public byte[][] scan(byte[] prefix) {
+        return execute('s', prefix);
+    }
+
+    public String[] scan(String prefix) {
+        byte[][] values = scan(prefix.getBytes());
+        if (values == null) {
+            return null;
+        }
+        String[] strings = new String[values.length];
+        for (int i = 0; i < values.length; ++i) {
+            strings[i] = new String(values[i]);
+        }
+        return strings;
+    }
+
+    public boolean reset() {
+        execute('r');
+        return mError == NO_ERROR;
+    }
+
+    public boolean password(byte[] oldPassword, byte[] newPassword) {
+        execute('p', oldPassword, newPassword);
+        return mError == NO_ERROR;
+    }
+
+    public boolean password(String oldPassword, String newPassword) {
+        return password(oldPassword.getBytes(), newPassword.getBytes());
+    }
+
+    public boolean password(byte[] password) {
+        return password(password, password);
+    }
+
+    public boolean password(String password) {
+        return password(password.getBytes());
+    }
+
+    public boolean lock() {
+        execute('l');
+        return mError == NO_ERROR;
+    }
+
+    public boolean unlock(byte[] password) {
+        execute('u', password);
+        return mError == NO_ERROR;
+    }
+
+    public boolean unlock(String password) {
+        return unlock(password.getBytes());
+    }
+
+    public int getLastError() {
+        return mError;
+    }
+
+    private byte[][] execute(int code, byte[]... parameters) {
+        mError = PROTOCOL_ERROR;
+
+        for (byte[] parameter : parameters) {
+            if (parameter == null || parameter.length > 65535) {
+                return null;
+            }
+        }
+
+        LocalSocket socket = new LocalSocket();
+        try {
+            socket.connect(sAddress);
+
+            OutputStream out = socket.getOutputStream();
+            out.write(code);
+            for (byte[] parameter : parameters) {
+                out.write(parameter.length >> 8);
+                out.write(parameter.length);
+                out.write(parameter);
+            }
+            out.flush();
+            socket.shutdownOutput();
+
+            InputStream in = socket.getInputStream();
+            code = in.read();
+            if (code == -1) {
+                return null;
+            }
+
+            ArrayList<byte[]> results = new ArrayList<byte[]>();
+            while (true) {
+                int i, j;
+                if ((i = in.read()) == -1) {
+                    break;
+                }
+                if ((j = in.read()) == -1) {
+                    return null;
+                }
+                byte[] result = new byte[i << 8 | j];
+                for (i = 0; i < result.length; i += j) {
+                    if ((j = in.read(result, i, result.length - i)) == -1) {
+                        return null;
+                    }
+                }
+                results.add(result);
+            }
+            mError = code;
+            return results.toArray(new byte[results.size()][]);
+        } catch (IOException e) {
+            // ignore
+        } finally {
+            try {
+                socket.close();
+            } catch (IOException e) {}
+        }
+        return null;
+    }
+}
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index eaab3eb..ac3b723 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -509,23 +509,26 @@
         }
         int speed = 0;
         String file = readFile("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state", '\0');
-        StringTokenizer st = new StringTokenizer(file, "\n ");
-        while (st.hasMoreElements()) {
-            String token = st.nextToken();
-            try {
-                long val = Long.parseLong(token);
-                tempSpeeds[speed] = val;
-                token = st.nextToken();
-                val = Long.parseLong(token);
-                tempTimes[speed] = val;
-                speed++;
-                if (speed == MAX_SPEEDS) break; // No more
-                if (localLOGV && out == null) {
-                    Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
-                            + "\t" + tempTimes[speed - 1]);
+        // Note: file may be null on kernels without cpufreq (i.e. the emulator's)
+        if (file != null) {
+            StringTokenizer st = new StringTokenizer(file, "\n ");
+            while (st.hasMoreElements()) {
+                String token = st.nextToken();
+                try {
+                    long val = Long.parseLong(token);
+                    tempSpeeds[speed] = val;
+                    token = st.nextToken();
+                    val = Long.parseLong(token);
+                    tempTimes[speed] = val;
+                    speed++;
+                    if (speed == MAX_SPEEDS) break; // No more
+                    if (localLOGV && out == null) {
+                        Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
+                              + "\t" + tempTimes[speed - 1]);
+                    }
+                } catch (NumberFormatException nfe) {
+                    Log.i(TAG, "Unable to parse time_in_state");
                 }
-            } catch (NumberFormatException nfe) {
-                Log.i(TAG, "Unable to parse time_in_state");
             }
         }
         if (out == null) {
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index 17d0f1d..8903ebd 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -32,23 +32,33 @@
 import java.io.IOException;
 
 /**
- * Backup agent for various system-managed data
+ * Backup agent for various system-managed data, currently just the system wallpaper
  */
 public class SystemBackupAgent extends BackupHelperAgent {
     private static final String TAG = "SystemBackupAgent";
 
+    // These paths must match what the WallpaperManagerService uses
     private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
     private static final String WALLPAPER_INFO = "/data/system/wallpaper_info.xml";
 
     @Override
-    public void onCreate() {
+    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState) throws IOException {
+        // We only back up the data under the current "wallpaper" schema with metadata
         addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
                 new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+        super.onBackup(oldState, data, newState);
     }
 
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
+        // On restore, we also support a previous data schema "system_files"
+        addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+                new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+        addHelper("system_files", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+                new String[] { WALLPAPER_IMAGE }));
+
         boolean success = false;
         try {
             super.onRestore(data, appVersionCode, newState);