Merge change 9551

* changes:
  Implement the jni bindings for Adapter2D.  Fix a refcount bug in the native adapter implementation.  Use adapters in Film to border the mipmaps.
diff --git a/Android.mk b/Android.mk
index 728ae46..275807a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -332,7 +332,13 @@
 
 framework_docs_LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 framework_docs_LOCAL_DROIDDOC_HTML_DIR := docs/html
+# The since flag (-since N.xml API_LEVEL) is used to add API Level information
+# to the reference documentation. Must be in order of oldest to newest.
 framework_docs_LOCAL_DROIDDOC_OPTIONS := \
+    -since ./frameworks/base/api/1.xml 1 \
+    -since ./frameworks/base/api/2.xml 2 \
+    -since ./frameworks/base/api/3.xml 3 \
+    -since ./frameworks/base/api/current.xml Donut \
 		-error 1 -error 2 -warning 3 -error 4 -error 6 -error 8 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index eac455e..637e0d8 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -37,6 +37,7 @@
 #include "netkeystore.h"
 #include "keymgmt.h"
 
+#define  DBG  1
 #define  CMD_PUT_WITH_FILE  "putfile"
 
 typedef void CMD_FUNC(LPC_MARSHAL *cmd, LPC_MARSHAL *reply);
@@ -397,12 +398,12 @@
 
         // read the command, execute and send the result back.
         if(read_marshal(s, &cmd)) goto err;
-        LOGI("new connection\n");
+        if (DBG) LOGD("new connection\n");
         execute(&cmd, &reply);
         write_marshal(s, &reply);
 err:
         memset(&reply, 0, sizeof(LPC_MARSHAL));
-        LOGI("closing connection\n");
+        if (DBG) LOGD("closing connection\n");
         close(s);
     }
 
diff --git a/core/java/android/net/http/EventHandler.java b/core/java/android/net/http/EventHandler.java
index 830d1f1..a035c19 100644
--- a/core/java/android/net/http/EventHandler.java
+++ b/core/java/android/net/http/EventHandler.java
@@ -141,7 +141,10 @@
      * SSL certificate error callback. Handles SSL error(s) on the way
      * up to the user. The callback has to make sure that restartConnection() is called,
      * otherwise the connection will be suspended indefinitely.
+     * @return True if the callback can handle the error, which means it will
+     *              call restartConnection() to unblock the thread later,
+     *              otherwise return false.
      */
-    public void handleSslErrorRequest(SslError error);
+    public boolean handleSslErrorRequest(SslError error);
 
 }
diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java
index 55b733f..8a69d0d 100644
--- a/core/java/android/net/http/HttpsConnection.java
+++ b/core/java/android/net/http/HttpsConnection.java
@@ -323,7 +323,10 @@
                 mSuspended = true;
             }
             // don't hold the lock while calling out to the event handler
-            eventHandler.handleSslErrorRequest(error);
+            boolean canHandle = eventHandler.handleSslErrorRequest(error);
+            if(!canHandle) {
+                throw new IOException("failed to handle "+ error);
+            }
             synchronized (mSuspendLock) {
                 if (mSuspended) {
                     try {
diff --git a/core/java/android/net/http/LoggingEventHandler.java b/core/java/android/net/http/LoggingEventHandler.java
index 1b18651..bdafa0b 100644
--- a/core/java/android/net/http/LoggingEventHandler.java
+++ b/core/java/android/net/http/LoggingEventHandler.java
@@ -82,9 +82,11 @@
         }
     }
 
-    public void handleSslErrorRequest(SslError error) {
+    public boolean handleSslErrorRequest(SslError error) {
         if (HttpLog.LOGV) {
             HttpLog.v("LoggingEventHandler: handleSslErrorRequest():" + error);
         }
+        // return false so that the caller thread won't wait forever
+        return false;
     }
 }
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index 5f84e57..c0dbf4d 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -1523,6 +1523,15 @@
                 ContactsContract.Intents.EXTRA_CREATE_DESCRIPTION;
 
         /**
+         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
+         * dialog location using screen coordinates. When not specified, the
+         * dialog will be centered.
+         *
+         * @hide pending API council review
+         */
+        public static final String EXTRA_TARGET_RECT = ContactsContract.Intents.EXTRA_TARGET_RECT;
+
+        /**
          * Intents related to the Contacts app UI.
          */
         public static final class UI {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 01189fe..227c675 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1009,6 +1009,8 @@
 
             public static final String PROTOCOL = "data5";
 
+            public static final String CUSTOM_PROTOCOL = "data6";
+
             /**
              * The predefined IM protocol types. The protocol can either be non-present, one
              * of these types, or a free-form string. These cases are encoded in the PROTOCOL
@@ -1019,6 +1021,7 @@
              * <li>custom:&lt;a string&gt;</li>
              * </ul>
              */
+            public static final int PROTOCOL_CUSTOM = -1;
             public static final int PROTOCOL_AIM = 0;
             public static final int PROTOCOL_MSN = 1;
             public static final int PROTOCOL_YAHOO = 2;
@@ -1027,31 +1030,6 @@
             public static final int PROTOCOL_GOOGLE_TALK = 5;
             public static final int PROTOCOL_ICQ = 6;
             public static final int PROTOCOL_JABBER = 7;
-
-            public static String encodePredefinedImProtocol(int protocol) {
-               return "pre:" + protocol;
-            }
-
-            public static String encodeCustomImProtocol(String protocolString) {
-               return "custom:" + protocolString;
-            }
-
-            public static Object decodeImProtocol(String encodedString) {
-               if (encodedString == null) {
-                   return null;
-               }
-
-               if (encodedString.startsWith("pre:")) {
-                   return Integer.parseInt(encodedString.substring(4));
-               }
-
-               if (encodedString.startsWith("custom:")) {
-                   return encodedString.substring(7);
-               }
-
-               throw new IllegalArgumentException(
-                       "the value is not a valid encoded protocol, " + encodedString);
-            }
         }
 
         /**
@@ -1397,6 +1375,13 @@
             "com.android.contacts.action.CREATE_DESCRIPTION";
 
         /**
+         * Optional extra used with {@link #SHOW_OR_CREATE_CONTACT} to specify a
+         * dialog location using screen coordinates. When not specified, the
+         * dialog will be centered.
+         */
+        public static final String EXTRA_TARGET_RECT = "target_rect";
+
+        /**
          * Intents related to the Contacts app UI.
          */
         public static final class UI {
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
new file mode 100644
index 0000000..d8509a0
--- /dev/null
+++ b/core/java/android/util/MathUtils.java
@@ -0,0 +1,168 @@
+/*
+ * 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.util;
+
+import java.util.Random;
+
+/**
+ * A class that contains utility methods related to numbers.
+ * 
+ * @hide Pending API council approval
+ */
+public final class MathUtils {
+    private static final Random sRandom = new Random();
+    private static final float DEG_TO_RAD = 3.1415926f / 180.0f;
+    private static final float RAD_TO_DEG = 180.0f / 3.1415926f;
+
+    private MathUtils() {
+    }
+
+    public static float abs(float v) {
+        return v > 0 ? v : -v; 
+    }
+
+    public static int constrain(int amount, int low, int high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    public static float constrain(float amount, float low, float high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    public static float log(float a) {
+        return (float) Math.log(a);
+    }
+
+    public static float exp(float a) {
+        return (float) Math.exp(a);
+    }
+
+    public static float pow(float a, float b) {
+        return (float) Math.pow(a, b);
+    }
+
+    public static float max(float a, float b) {
+        return a > b ? a : b;
+    }
+
+    public static float max(int a, int b) {
+        return a > b ? a : b;
+    }
+
+    public static float max(float a, float b, float c) {
+        return a > b ? (a > c ? a : c) : (b > c ? b : c);
+    }
+
+    public static float max(int a, int b, int c) {
+        return a > b ? (a > c ? a : c) : (b > c ? b : c);
+    }
+
+    public static float min(float a, float b) {
+        return a < b ? a : b;
+    }
+
+    public static float min(int a, int b) {
+        return a < b ? a : b;
+    }
+
+    public static float min(float a, float b, float c) {
+        return a < b ? (a < c ? a : c) : (b < c ? b : c);
+    }
+
+    public static float min(int a, int b, int c) {
+        return a < b ? (a < c ? a : c) : (b < c ? b : c);
+    }
+
+    public static float dist(float x1, float y1, float x2, float y2) {
+        final float x = (x2 - x1);
+        final float y = (y2 - y1);
+        return (float) Math.sqrt(x * x + y * y);
+    }
+
+    public static float dist(float x1, float y1, float z1, float x2, float y2, float z2) {
+        final float x = (x2 - x1);
+        final float y = (y2 - y1);
+        final float z = (z2 - z1);
+        return (float) Math.sqrt(x * x + y * y + z * z);
+    }
+
+    public static float mag(float a, float b) {
+        return (float) Math.sqrt(a * a + b * b);
+    }
+
+    public static float mag(float a, float b, float c) {
+        return (float) Math.sqrt(a * a + b * b + c * c);
+    }
+
+    public static float sq(float v) {
+        return v * v;
+    }
+
+    public static float radians(float degrees) {
+        return degrees * DEG_TO_RAD;
+    }
+
+    public static float degress(float radians) {
+        return radians * RAD_TO_DEG;
+    }
+
+    public static float acos(float value) {
+        return (float) Math.acos(value);
+    }
+
+    public static float asin(float value) {
+        return (float) Math.asin(value);
+    }
+
+    public static float atan(float value) {
+        return (float) Math.atan(value);
+    }
+
+    public static float atan2(float a, float b) {
+        return (float) Math.atan2(a, b);
+    }
+
+    public static float tan(float angle) {
+        return (float) Math.tan(angle);
+    }    
+
+    public static float lerp(float start, float stop, float amount) {
+        return start + (stop - start) * amount;
+    }
+    
+    public static int random(int howbig) {
+        return (int) (sRandom.nextFloat() * howbig);
+    }
+
+    public static int random(int howsmall, int howbig) {
+        if (howsmall >= howbig) return howsmall;
+        return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
+    }
+    
+    public static float random(float howbig) {
+        return sRandom.nextFloat() * howbig;
+    }
+
+    public static float random(float howsmall, float howbig) {
+        if (howsmall >= howbig) return howsmall;
+        return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
+    }
+
+    public static void randomSeed(long seed) {
+        sRandom.setSeed(seed);
+    }
+}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 7b91724..c81c4b6 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -23,9 +23,12 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 /**
  * CookieManager manages cookies according to RFC2109 spec.
@@ -190,6 +193,14 @@
         }
     }
 
+    private static final CookieComparator COMPARATOR = new CookieComparator();
+
+    private static final class CookieComparator implements Comparator<Cookie> {
+        public int compare(Cookie cookie1, Cookie cookie2) {
+            return cookie2.path.length() - cookie1.path.length();
+        }
+    }
+
     private CookieManager() {
     }
 
@@ -401,8 +412,8 @@
         long now = System.currentTimeMillis();
         boolean secure = HTTPS.equals(uri.mScheme);
         Iterator<Cookie> iter = cookieList.iterator();
-        StringBuilder ret = new StringBuilder(256);
 
+        SortedSet<Cookie> cookieSet = new TreeSet<Cookie>(COMPARATOR);
         while (iter.hasNext()) {
             Cookie cookie = iter.next();
             if (cookie.domainMatch(hostAndPath[0]) &&
@@ -413,19 +424,26 @@
                     && (!cookie.secure || secure)
                     && cookie.mode != Cookie.MODE_DELETED) {
                 cookie.lastAcessTime = now;
-
-                if (ret.length() > 0) {
-                    ret.append(SEMICOLON);
-                    // according to RC2109, SEMICOLON is office separator,
-                    // but when log in yahoo.com, it needs WHITE_SPACE too.
-                    ret.append(WHITE_SPACE);
-                }
-
-                ret.append(cookie.name);
-                ret.append(EQUAL);
-                ret.append(cookie.value);
+                cookieSet.add(cookie);
             }
         }
+
+        StringBuilder ret = new StringBuilder(256);
+        Iterator<Cookie> setIter = cookieSet.iterator();
+        while (setIter.hasNext()) {
+            Cookie cookie = setIter.next();
+            if (ret.length() > 0) {
+                ret.append(SEMICOLON);
+                // according to RC2109, SEMICOLON is official separator,
+                // but when log in yahoo.com, it needs WHITE_SPACE too.
+                ret.append(WHITE_SPACE);
+            }
+
+            ret.append(cookie.name);
+            ret.append(EQUAL);
+            ret.append(cookie.value);
+        }
+
         if (ret.length() > 0) {
             if (DebugFlags.COOKIE_MANAGER) {
                 Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret);
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 50436d8..7fff014 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -104,6 +104,7 @@
     private String   mErrorDescription;
     private SslError mSslError;
     private RequestHandle mRequestHandle;
+    private RequestHandle mSslErrorRequestHandle;
 
     // Request data. It is only valid when we are doing a load from the
     // cache. It is needed if the cache returns a redirect
@@ -673,7 +674,7 @@
      * IMPORTANT: as this is called from network thread, can't call native
      * directly
      */
-    public void handleSslErrorRequest(SslError error) {
+    public boolean handleSslErrorRequest(SslError error) {
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG,
                     "LoadListener.handleSslErrorRequest(): url:" + url() +
@@ -681,6 +682,15 @@
                     " certificate: " + error.getCertificate());
         }
         sendMessageInternal(obtainMessage(MSG_SSL_ERROR, error));
+        // if it has been canceled, return false so that the network thread
+        // won't be blocked. If it is not canceled, save the mRequestHandle
+        // so that if it is canceled when MSG_SSL_ERROR is handled, we can
+        // still call handleSslErrorResponse which will call restartConnection
+        // to unblock the network thread.
+        if (!mCancelled) {
+            mSslErrorRequestHandle = mRequestHandle;
+        }
+        return !mCancelled;
     }
 
     // Handle the ssl error on the WebCore thread.
@@ -688,7 +698,10 @@
         if (!mCancelled) {
             mSslError = error;
             Network.getInstance(mContext).handleSslErrorRequest(this);
+        } else if (mSslErrorRequestHandle != null) {
+            mSslErrorRequestHandle.handleSslErrorResponse(true);
         }
+        mSslErrorRequestHandle = null;
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
new file mode 100644
index 0000000..ccb537a
--- /dev/null
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.SocialContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.SocialContract.Activities;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+
+/* Widget that is used across system apps for displaying a header banner with contact info */
+public class ContactHeaderWidget extends FrameLayout implements View.OnClickListener {
+
+    private static final String TAG = "ContactHeaderWidget";
+
+    private TextView mDisplayNameView;
+    private TextView mPhoneticNameView;
+    private CheckBox mStarredView;
+    private ImageView mPhotoView;
+    private TextView mStatusView;
+    private int mNoPhotoResource;
+    private QueryHandler mQueryHandler;
+
+    protected long mContactId;
+    protected Uri mContactDataUri;
+    protected Uri mContactUri;
+    protected Uri mStatusUri;
+
+    protected ContentResolver mContentResolver;
+
+    //Projection used for the summary info in the header.
+    protected static final String[] HEADER_PROJECTION = new String[] {
+        Contacts.DISPLAY_NAME,
+        Contacts.STARRED,
+        Contacts.PHOTO_ID,
+    };
+    protected static final int HEADER_DISPLAY_NAME_COLUMN_INDEX = 0;
+    //TODO: We need to figure out how we're going to get the phonetic name.
+    //static final int HEADER_PHONETIC_NAME_COLUMN_INDEX
+    protected static final int HEADER_STARRED_COLUMN_INDEX = 1;
+    protected static final int HEADER_PHOTO_ID_COLUMN_INDEX = 2;
+
+    //Projection used for finding the most recent social status.
+    protected static final String[] SOCIAL_PROJECTION = new String[] {
+        Activities.TITLE,
+        Activities.PUBLISHED,
+    };
+    protected static final int SOCIAL_TITLE_COLUMN_INDEX = 0;
+    protected static final int SOCIAL_PUBLISHED_COLUMN_INDEX = 1;
+
+    //Projection used for looking up contact id from phone number
+    protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
+        RawContacts.CONTACT_ID,
+    };
+    protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+
+    //Projection used for looking up contact id from email address
+    protected static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
+        RawContacts.CONTACT_ID,
+    };
+    protected static final int EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+
+
+    private static final int TOKEN_CONTACT_INFO = 0;
+    private static final int TOKEN_SOCIAL = 1;
+
+    public ContactHeaderWidget(Context context) {
+        this(context, null);
+    }
+
+    public ContactHeaderWidget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public ContactHeaderWidget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        mContentResolver = mContext.getContentResolver();
+
+        LayoutInflater inflater =
+            (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.contact_header, this);
+
+        mDisplayNameView = (TextView) findViewById(R.id.name);
+        mPhoneticNameView = (TextView) findViewById(R.id.phonetic_name);
+        mStarredView = (CheckBox) findViewById(R.id.star);
+        mStarredView.setOnClickListener(this);
+        // Don't show start by default.
+        mStarredView.setVisibility(View.GONE);
+        mPhotoView = (ImageView) findViewById(R.id.photo);
+        mStatusView = (TextView) findViewById(R.id.status);
+
+        // Set the photo with a random "no contact" image
+        long now = SystemClock.elapsedRealtime();
+        int num = (int) now & 0xf;
+        if (num < 9) {
+            // Leaning in from right, common
+            mNoPhotoResource = R.drawable.ic_contact_picture;
+        } else if (num < 14) {
+            // Leaning in from left uncommon
+            mNoPhotoResource = R.drawable.ic_contact_picture_2;
+        } else {
+            // Coming in from the top, rare
+            mNoPhotoResource = R.drawable.ic_contact_picture_3;
+        }
+
+        mQueryHandler = new QueryHandler(mContentResolver);
+    }
+
+    private class QueryHandler extends AsyncQueryHandler {
+
+        public QueryHandler(ContentResolver cr) {
+            super(cr);
+        }
+
+        @Override
+        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+            try{
+                if (token == TOKEN_CONTACT_INFO) {
+                    bindContactInfo(cursor);
+                    invalidate();
+                } else if (token == TOKEN_SOCIAL) {
+                    bindSocial(cursor);
+                    invalidate();
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+    }
+
+
+    /** {@inheritDoc} */
+    public void onQueryComplete(int token, Object cookie, Cursor cursor) {
+        try{
+            if (token == TOKEN_CONTACT_INFO) {
+                bindContactInfo(cursor);
+                invalidate();
+            } else if (token == TOKEN_SOCIAL) {
+                bindSocial(cursor);
+                invalidate();
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+    /**
+     * Turn on/off showing of the star element.
+     */
+    public void showStar(boolean showStar) {
+        mStarredView.setVisibility(showStar ? View.VISIBLE : View.GONE);
+    }
+
+    /**
+     * Convenience method for binding all available data from an existing
+     * contact.
+     *
+     * @param contactId the contact id of the contact whose info should be displayed.
+     */
+    public void bindFromContactId(long contactId) {
+        mContactId = contactId;
+        mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId);
+        mContactDataUri = Uri.withAppendedPath(mContactUri, Contacts.Data.CONTENT_DIRECTORY);
+        mStatusUri = ContentUris.withAppendedId(
+                SocialContract.Activities.CONTENT_CONTACT_STATUS_URI, mContactId);
+        redrawHeader();
+    }
+
+    /**
+     * Convenience method for binding all available data from an existing
+     * contact.
+     *
+     * @param emailAddress The email address used to do a reverse lookup in
+     * the contacts database. If more than one contact contains this email
+     * address, one of them will be chosen to bind to.
+     */
+    public void bindFromEmail(String emailAddress) {
+        Cursor c = null;
+        try {
+            c = mContentResolver.query(Uri.withAppendedPath(
+                    RawContacts.CONTENT_FILTER_EMAIL_URI, Uri.encode(emailAddress)),
+                    EMAIL_LOOKUP_PROJECTION, null, null, null);
+            if (c.moveToFirst()) {
+                long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+                bindFromContactId(contactId);
+            }
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    /**
+     * Convenience method for binding all available data from an existing
+     * contact.
+     *
+     * @param number The phone number used to do a reverse lookup in
+     * the contacts database. If more than one contact contains this phone
+     * number, one of them will be chosen to bind to.
+     */
+    public void bindFromPhoneNumber(String number) {
+        Cursor c = null;
+        try {
+            c = mContentResolver.query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
+                    PHONE_LOOKUP_PROJECTION, null, null, null);
+            if (c.moveToFirst()) {
+                long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+                bindFromContactId(contactId);
+            }
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    protected void redrawHeader() {
+        if (mContactDataUri != null) {
+            mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, mContactDataUri, HEADER_PROJECTION,
+                    null, null, null);
+        }
+
+        if (mStatusUri != null) {
+            mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION,
+                    null, null, null);
+        }
+    }
+
+    protected void bindContactInfo(Cursor c) {
+        if (c == null) {
+            return;
+        }
+        if (c.moveToFirst()) {
+            //Set name
+            String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
+            Log.i(TAG, displayName);
+            mDisplayNameView.setText(displayName);
+            //TODO: Bring back phonetic name
+            /*if (mPhoneticNameView != null) {
+                String phoneticName = c.getString(CONTACT_PHONETIC_NAME_COLUMN);
+                mPhoneticNameView.setText(phoneticName);
+            }*/
+
+            //Set starred
+            mStarredView.setChecked(c.getInt(HEADER_STARRED_COLUMN_INDEX) == 1);
+
+            //Set the photo
+            Bitmap photoBitmap = loadContactPhoto(c.getLong(HEADER_PHOTO_ID_COLUMN_INDEX), null);
+            if (photoBitmap == null) {
+                photoBitmap = loadPlaceholderPhoto(null);
+            }
+            mPhotoView.setImageBitmap(photoBitmap);
+        }
+    }
+
+    protected void bindSocial(Cursor c) {
+        if (c == null) {
+            return;
+        }
+        if (c.moveToFirst()) {
+            String status = c.getString(SOCIAL_TITLE_COLUMN_INDEX);
+            mStatusView.setText(status);
+        }
+    }
+
+    public void onClick(View view) {
+        if (view.getId() == R.id.star) {
+            ContentValues values = new ContentValues(1);
+            values.put(Contacts.STARRED, mStarredView.isChecked());
+            mContentResolver.update(mContactUri, values, null, null);
+        }
+    }
+
+    private Bitmap loadContactPhoto(long photoId, BitmapFactory.Options options) {
+        Cursor photoCursor = null;
+        Bitmap photoBm = null;
+
+        try {
+            photoCursor = mContentResolver.query(
+                    ContentUris.withAppendedId(Data.CONTENT_URI, photoId),
+                    new String[] { Photo.PHOTO },
+                    null, null, null);
+
+            if (photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
+                byte[] photoData = photoCursor.getBlob(0);
+                photoBm = BitmapFactory.decodeByteArray(photoData, 0,
+                        photoData.length, options);
+            }
+        } finally {
+            if (photoCursor != null) {
+                photoCursor.close();
+            }
+        }
+
+        return photoBm;
+    }
+
+    private Bitmap loadPlaceholderPhoto(BitmapFactory.Options options) {
+        if (mNoPhotoResource == 0) {
+            return null;
+        }
+        return BitmapFactory.decodeResource(mContext.getResources(),
+                mNoPhotoResource, options);
+    }
+}
diff --git a/core/res/res/drawable/contact_header_bg.9.png b/core/res/res/drawable/contact_header_bg.9.png
new file mode 100644
index 0000000..7f9a5a3
--- /dev/null
+++ b/core/res/res/drawable/contact_header_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable/contact_picture_bg.9.png b/core/res/res/drawable/contact_picture_bg.9.png
new file mode 100644
index 0000000..ae9c709
--- /dev/null
+++ b/core/res/res/drawable/contact_picture_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable/ic_contact_picture_2.png b/core/res/res/drawable/ic_contact_picture_2.png
new file mode 100644
index 0000000..8b184af
--- /dev/null
+++ b/core/res/res/drawable/ic_contact_picture_2.png
Binary files differ
diff --git a/core/res/res/drawable/ic_contact_picture_3.png b/core/res/res/drawable/ic_contact_picture_3.png
new file mode 100644
index 0000000..a2d08b5
--- /dev/null
+++ b/core/res/res/drawable/ic_contact_picture_3.png
Binary files differ
diff --git a/core/res/res/layout-ja/contact_header_name.xml b/core/res/res/layout-ja/contact_header_name.xml
new file mode 100644
index 0000000..03332b1
--- /dev/null
+++ b/core/res/res/layout-ja/contact_header_name.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+
+<!-- In Japanese-language locales, the "Name" field contains two separate
+     TextViews: the name itself, and also the phonetic ("furigana") field. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="0dip"
+    android:layout_weight="1"
+    android:layout_height="wrap_content">
+
+    <TextView android:id="@+id/name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+    	android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    	android:textColor="@android:color/secondary_text_light"
+        />
+
+    <TextView android:id="@+id/phonetic_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+    	android:textAppearance="?android:attr/textAppearanceSmallInverse"
+    	android:textColor="@android:color/secondary_text_light"
+        />
+
+</LinearLayout>
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
new file mode 100644
index 0000000..04b34b8
--- /dev/null
+++ b/core/res/res/layout/contact_header.xml
@@ -0,0 +1,56 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:id="@+id/banner"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:background="@drawable/contact_header_bg"
+    android:paddingRight="5dip"
+    android:gravity="center_vertical">
+    
+    <ImageView android:id="@+id/photo"
+        android:layout_width="64dip"
+        android:layout_height="64dip"
+        android:layout_marginRight="7dip"
+        android:layout_marginLeft="2dip"
+        android:scaleType="fitCenter"
+        android:background="@drawable/contact_picture_bg"/>
+    
+    <LinearLayout
+        android:layout_width="0dip"
+        android:layout_height="fill_parent"
+        android:layout_weight="1"
+        android:orientation="vertical">
+
+        <!-- "Name" field is locale-specific. -->
+        <include layout="@layout/contact_header_name"/>
+
+        <TextView android:id="@+id/status"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:maxLines="2"/>
+                
+    </LinearLayout>
+
+    <CheckBox android:id="@+id/star"
+        style="?android:attr/starStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/contact_header_name.xml b/core/res/res/layout/contact_header_name.xml
new file mode 100644
index 0000000..aec943e
--- /dev/null
+++ b/core/res/res/layout/contact_header_name.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<!-- In the default locale, the "Name" field is a single TextView -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/name"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    android:textColor="@android:color/secondary_text_light"
+    android:maxLines="2"
+    android:ellipsize="end"
+    />
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 47f8c03..6b792c6 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -101,16 +101,16 @@
     <string name="numeric_date_template">"%s. %s. %s."</string>
     <string name="month_day_year">%Y년 %-m월 %-e일</string>
     <string name="time_of_day">%p %-l:%M:%S</string>
-    <string name="date_and_time">%Y. %-m. %-e. %p %-l:%M:%S</string>
+    <string name="date_and_time">%Y년 %-m월 %-e일 %p %-l:%M:%S</string>
     <string name="date_time">%1$s %2$s</string>
     <string name="time_date">%3$s %1$s</string>
-    <string name="abbrev_month_day_year">%Y. %-m. %-e.</string>
+    <string name="abbrev_month_day_year">%Y년 %-m월 %-e일</string>
     <string name="month_day">%B %-e일</string>
     <string name="month">%-B</string>
     <string name="month_year">%Y년 %B</string>
-    <string name="abbrev_month_day">%-m. %-e.</string>
+    <string name="abbrev_month_day">%-m월 %-e일</string>
     <string name="abbrev_month">%-m월</string>
-    <string name="abbrev_month_year">%Y. %-m.</string>
+    <string name="abbrev_month_year">%Y년 %-m월</string>
     <string name="time1_time2">%1$s ~ %2$s</string>
     <string name="date1_date2">%2$s ~ %5$s</string>
     <string name="numeric_md1_md2">%2$s. %3$s ~ %7$s. %8$s</string>
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 3fc391c..5cefaa3 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.util.MathUtils;
+
 import java.util.HashMap;
 import java.util.Locale;
 
@@ -105,6 +107,92 @@
     }
 
     /**
+     * Returns the hue component of a color int.
+     * 
+     * @return A value between 0.0f and 1.0f
+     * 
+     * @hide Pending API council
+     */
+    public static float hue(int color) {
+        int r = (color >> 16) & 0xFF;
+        int g = (color >> 8) & 0xFF;
+        int b = color & 0xFF;
+
+        int V = Math.max(b, Math.max(r, g));
+        int temp = Math.min(b, Math.min(r, g));
+
+        float H;
+
+        if (V == temp) {
+            H = 0;
+        } else {
+            final float vtemp = (float) (V - temp);
+            final float cr = (V - r) / vtemp;
+            final float cg = (V - g) / vtemp;
+            final float cb = (V - b) / vtemp;
+
+            if (r == V) {
+                H = cb - cg;
+            } else if (g == V) {
+                H = 2 + cr - cb;
+            } else {
+                H = 4 + cg - cr;
+            }
+
+            H /= 6.f;
+            if (H < 0) {
+                H++;
+            }
+        }
+
+        return H;
+    }
+
+    /**
+     * Returns the saturation component of a color int.
+     * 
+     * @return A value between 0.0f and 1.0f
+     * 
+     * @hide Pending API council
+     */
+    public static float saturation(int color) {
+        int r = (color >> 16) & 0xFF;
+        int g = (color >> 8) & 0xFF;
+        int b = color & 0xFF;
+
+
+        int V = Math.max(b, Math.max(r, g));
+        int temp = Math.min(b, Math.min(r, g));
+
+        float S;
+
+        if (V == temp) {
+            S = 0;
+        } else {
+            S = (V - temp) / (float) V;
+        }
+
+        return S;
+    }
+
+    /**
+     * Returns the brightness component of a color int.
+     * 
+     * @return A value between 0.0f and 1.0f
+     * 
+     * @hide Pending API council
+     */
+    public static float brightness(int color) {
+        int r = (color >> 16) & 0xFF;
+        int g = (color >> 8) & 0xFF;
+        int b = color & 0xFF;
+
+        int V = Math.max(b, Math.max(r, g));
+
+        return (V / 255.f);
+    }
+
+    /**
      * Parse the color string, and return the corresponding color-int.
      * If the string cannot be parsed, throws an IllegalArgumentException
      * exception. Supported formats are:
@@ -134,6 +222,87 @@
     }
 
     /**
+     * Convert HSB components to an ARGB color. Alpha set to 0xFF.
+     *     hsv[0] is Hue [0 .. 1)
+     *     hsv[1] is Saturation [0...1]
+     *     hsv[2] is Value [0...1]
+     * If hsv values are out of range, they are pinned.
+     * @param hsb  3 element array which holds the input HSB components.
+     * @return the resulting argb color
+     * 
+     * @hide Pending API council
+     */
+    public static int HSBtoColor(float[] hsb) {
+        return HSBtoColor(hsb[0], hsb[1], hsb[2]);
+    }
+    
+    /**
+     * Convert HSB components to an ARGB color. Alpha set to 0xFF.
+     *     hsv[0] is Hue [0 .. 1)
+     *     hsv[1] is Saturation [0...1]
+     *     hsv[2] is Value [0...1]
+     * If hsv values are out of range, they are pinned.
+     * @param h Hue component
+     * @param s Saturation component
+     * @param b Brightness component
+     * @return the resulting argb color
+     * 
+     * @hide Pending API council
+     */
+    public static int HSBtoColor(float h, float s, float b) {
+        h = MathUtils.constrain(h, 0.0f, 1.0f);
+        s = MathUtils.constrain(s, 0.0f, 1.0f);
+        b = MathUtils.constrain(b, 0.0f, 1.0f);
+        
+        float red = 0.0f;
+        float green = 0.0f;
+        float blue = 0.0f;
+        
+        final float hf = (h - (int) h) * 6.0f;
+        final int ihf = (int) hf;
+        final float f = hf - ihf;
+        final float pv = b * (1.0f - s);
+        final float qv = b * (1.0f - s * f);
+        final float tv = b * (1.0f - s * (1.0f - f));
+
+        switch (ihf) {
+            case 0:         // Red is the dominant color
+                red = b;
+                green = tv;
+                blue = pv;
+                break;
+            case 1:         // Green is the dominant color
+                red = qv;
+                green = b;
+                blue = pv;
+                break;
+            case 2:
+                red = pv;
+                green = b;
+                blue = tv;
+                break;
+            case 3:         // Blue is the dominant color
+                red = pv;
+                green = qv;
+                blue = b;
+                break;
+            case 4:
+                red = tv;
+                green = pv;
+                blue = b;
+                break;
+            case 5:         // Red is the dominant color
+                red = b;
+                green = pv;
+                blue = qv;
+                break;
+        }
+
+        return 0xFF000000 | (((int) (red * 255.0f)) << 16) |
+                (((int) (green * 255.0f)) << 8) | ((int) (blue * 255.0f));
+    }
+
+    /**
      * Convert RGB components to HSV.
      *     hsv[0] is Hue [0 .. 360)
      *     hsv[1] is Saturation [0...1]
@@ -193,25 +362,24 @@
         return nativeHSVToColor(alpha, hsv);
     }
 
-    private static native void nativeRGBToHSV(int red, int greed, int blue,
-                                              float hsv[]);
+    private static native void nativeRGBToHSV(int red, int greed, int blue, float hsv[]); 
     private static native int nativeHSVToColor(int alpha, float hsv[]);
 
     private static final HashMap<String, Integer> sColorNameMap;
 
     static {
-        sColorNameMap = new HashMap();
-        sColorNameMap.put("black", Integer.valueOf(BLACK));
-        sColorNameMap.put("darkgray", Integer.valueOf(DKGRAY));
-        sColorNameMap.put("gray", Integer.valueOf(GRAY));
-        sColorNameMap.put("lightgray", Integer.valueOf(LTGRAY));
-        sColorNameMap.put("white", Integer.valueOf(WHITE));
-        sColorNameMap.put("red", Integer.valueOf(RED));
-        sColorNameMap.put("green", Integer.valueOf(GREEN));
-        sColorNameMap.put("blue", Integer.valueOf(BLUE));
-        sColorNameMap.put("yellow", Integer.valueOf(YELLOW));
-        sColorNameMap.put("cyan", Integer.valueOf(CYAN));
-        sColorNameMap.put("magenta", Integer.valueOf(MAGENTA));
+        sColorNameMap = new HashMap<String, Integer>();
+        sColorNameMap.put("black", BLACK);
+        sColorNameMap.put("darkgray", DKGRAY);
+        sColorNameMap.put("gray", GRAY);
+        sColorNameMap.put("lightgray", LTGRAY);
+        sColorNameMap.put("white", WHITE);
+        sColorNameMap.put("red", RED);
+        sColorNameMap.put("green", GREEN);
+        sColorNameMap.put("blue", BLUE);
+        sColorNameMap.put("yellow", YELLOW);
+        sColorNameMap.put("cyan", CYAN);
+        sColorNameMap.put("magenta", MAGENTA);
     }
 }
 
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java
index b1b78ea..989432a 100644
--- a/keystore/java/android/security/CertTool.java
+++ b/keystore/java/android/security/CertTool.java
@@ -209,6 +209,10 @@
             }
             freeX509Certificate(handle);
         }
-        if (intent != null) context.startActivity(intent);
+        if (intent != null) {
+            context.startActivity(intent);
+        } else {
+            Log.w("CertTool", "incorrect data for addCertificate()");
+        }
     }
 }
diff --git a/keystore/java/android/security/ServiceCommand.java b/keystore/java/android/security/ServiceCommand.java
index 6178d59..dddf654 100644
--- a/keystore/java/android/security/ServiceCommand.java
+++ b/keystore/java/android/security/ServiceCommand.java
@@ -49,6 +49,8 @@
 
     public static final int BUFFER_LENGTH = 4096;
 
+    private static final boolean DBG = true;
+
     private String mServiceName;
     private String mTag;
     private InputStream mIn;
@@ -59,7 +61,7 @@
         if (mSocket != null) {
             return true;
         }
-        Log.i(mTag, "connecting...");
+        if (DBG) Log.d(mTag, "connecting...");
         try {
             mSocket = new LocalSocket();
 
@@ -78,7 +80,7 @@
     }
 
     private void disconnect() {
-        Log.i(mTag,"disconnecting...");
+        if (DBG) Log.d(mTag,"disconnecting...");
         try {
             if (mSocket != null) mSocket.close();
         } catch (IOException ex) { }
@@ -105,7 +107,7 @@
                 }
                 off += count;
             } catch (IOException ex) {
-                Log.e(mTag,"read exception");
+                Log.e(mTag,"read exception", ex);
                 break;
             }
         }
@@ -156,7 +158,7 @@
             mOut.write(buf, 0, 8);
             mOut.write(data, 0, len);
         } catch (IOException ex) {
-            Log.e(mTag,"write error");
+            Log.e(mTag,"write error", ex);
             disconnect();
             return false;
         }
diff --git a/libs/rs/java/Grass/res/raw/grass.c b/libs/rs/java/Grass/res/raw/grass.c
index b1b89f0..79cf483 100644
--- a/libs/rs/java/Grass/res/raw/grass.c
+++ b/libs/rs/java/Grass/res/raw/grass.c
@@ -1,21 +1,19 @@
-/*
- * 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.
- */
- 
+// 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.
+
 #pragma version(1)
-#pragma stateVertex(default)
+#pragma stateVertex(PVBackground)
 #pragma stateFragment(PFBackground)
 #pragma stateFragmentStore(PFSBackground)
 
@@ -23,7 +21,8 @@
 #define WVGA_PORTRAIT_HEIGHT 762.0f
 
 #define RSID_STATE 0
-#define RSID_FRAMECOUNT 0
+#define RSID_FRAME_COUNT 0
+#define RSID_BLADES_COUNT 1
 
 #define RSID_SKY_TEXTURES 1
 #define RSID_SKY_TEXTURE_NIGHT 0
@@ -31,6 +30,21 @@
 #define RSID_SKY_TEXTURE_NOON 2
 #define RSID_SKY_TEXTURE_SUNSET 3
 
+#define RSID_BLADES 2
+#define BLADE_STRUCT_FIELDS_COUNT 12
+#define BLADE_STRUCT_DEGREE 0
+#define BLADE_STRUCT_SIZE 1
+#define BLADE_STRUCT_XPOS 2
+#define BLADE_STRUCT_YPOS 3
+#define BLADE_STRUCT_OFFSET 4
+#define BLADE_STRUCT_SCALE 5
+#define BLADE_STRUCT_LENGTHX 6
+#define BLADE_STRUCT_LENGTHY 7
+#define BLADE_STRUCT_HARDNESS 8
+#define BLADE_STRUCT_H 9
+#define BLADE_STRUCT_S 10
+#define BLADE_STRUCT_B 11
+
 #define MIDNIGHT 0.0f
 #define MORNING 0.375f
 #define AFTERNOON 0.6f
@@ -38,6 +52,8 @@
 
 #define SECONDS_IN_DAY 24.0f * 3600.0f
 
+#define PI 3.1415926f
+
 #define REAL_TIME 0
 
 float time(int frameCount) {
@@ -51,10 +67,6 @@
     color(1.0f, 1.0f, 1.0f, a);
 }
 
-float norm(float a, float start, float end) {
-    return (a - start) / (end - start);
-}
-
 void drawNight() {
     bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_NIGHT));
     // NOTE: Hacky way to draw the night sky
@@ -76,37 +88,111 @@
     drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
 }
 
+void drawBlade(int index, float now) {
+    float offset = loadF(RSID_BLADES, index + BLADE_STRUCT_OFFSET);
+    float scale = loadF(RSID_BLADES, index + BLADE_STRUCT_SCALE);
+    float degree = loadF(RSID_BLADES, index + BLADE_STRUCT_DEGREE);
+    float hardness = loadF(RSID_BLADES, index + BLADE_STRUCT_HARDNESS);
+    
+    float xpos = loadF(RSID_BLADES, index + BLADE_STRUCT_XPOS);
+    float ypos = loadF(RSID_BLADES, index + BLADE_STRUCT_YPOS);
+
+    float lengthX = loadF(RSID_BLADES, index + BLADE_STRUCT_LENGTHX);
+    float lengthY = loadF(RSID_BLADES, index + BLADE_STRUCT_LENGTHY);
+
+    int size = loadF(RSID_BLADES, index + BLADE_STRUCT_SIZE);
+
+    float h = loadF(RSID_BLADES, index + BLADE_STRUCT_H);
+    float s = loadF(RSID_BLADES, index + BLADE_STRUCT_S);
+    float b = loadF(RSID_BLADES, index + BLADE_STRUCT_B);
+
+    float newB = 1.0f;
+    if (now >= MIDNIGHT && now < MORNING) {
+        newB = now / MORNING;
+    }
+
+    if (now >= AFTERNOON && now < DUSK) {
+        newB = 1.0f - normf(AFTERNOON, DUSK, now);
+    }
+
+    if (now >= DUSK) {
+        newB = 0.0f;
+    }
+
+    hsb(h, s, lerpf(0, b, newB), 1.0f);
+
+    float targetDegree = 0.0f; // TODO Compute
+    degree += (targetDegree - degree) * 0.3f;
+
+    float angle = PI / 2.0f;
+    
+    float currentX = xpos;
+    float currentY = ypos;
+    
+    int i = size;
+
+    for ( ; i > 0; i--) {
+        float nextX = currentX - cosf(angle) * size * lengthX;
+        float nextY = currentY - sinf(angle) * size * lengthY;
+        angle += degree * hardness;
+
+        drawQuad(nextX + (i - 1) * scale, nextY, 0.0f,
+                 nextX - (i - 1) * scale, nextY, 0.0f,
+                 currentX - i * scale, currentY + 0.7f, 0.0f,
+                 currentX + i * scale, currentY + 0.7f, 0.0f);
+
+        currentX = nextX;
+        currentY = nextY;
+    }
+    
+    storeF(RSID_BLADES, index + BLADE_STRUCT_DEGREE, degree);
+}
+
+void drawBlades(float now) {
+    bindTexture(NAMED_PFBackground, 0, 0);    
+
+    int bladesCount = loadI32(RSID_STATE, RSID_BLADES_COUNT);
+    int count = bladesCount * BLADE_STRUCT_FIELDS_COUNT;
+
+    int i = 0;
+    for ( ; i < count; i += BLADE_STRUCT_FIELDS_COUNT) {
+        drawBlade(i, now);
+    }
+}
+
 int main(int launchID) {
-    int frameCount = loadI32(RSID_STATE, RSID_FRAMECOUNT);
+    int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT);
     float now = time(frameCount);
     alpha(1.0f);
 
     if (now >= MIDNIGHT && now < MORNING) {
         drawNight();
-        alpha(norm(now, MIDNIGHT, MORNING));
+        alpha(normf(MIDNIGHT, MORNING, now));
         drawSunrise();
     }
     
     if (now >= MORNING && now < AFTERNOON) {
         drawSunrise();
-        alpha(norm(now, MORNING, AFTERNOON));
+        alpha(normf(MORNING, AFTERNOON, now));
         drawNoon();
     }
 
     if (now >= AFTERNOON && now < DUSK) {
         drawNoon();
-        alpha(norm(now, AFTERNOON, DUSK));
+        alpha(normf(AFTERNOON, DUSK, now));
         drawSunset();
     }
     
     if (now >= DUSK) {
-        drawSunset();
-        alpha(norm(now, DUSK, 1.0f));
         drawNight();
+        alpha(1.0f - normf(DUSK, 1.0f, now));
+        drawSunset();
     }
+    
+    drawBlades(now);
 
     frameCount++;
-    storeI32(RSID_STATE, RSID_FRAMECOUNT, frameCount);
+    storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount);
 
     return 1;
 }
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
index 70cb012..435b5ce 100644
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -23,20 +23,45 @@
 import static android.renderscript.RenderScript.DepthFunc.*;
 import static android.renderscript.RenderScript.BlendSrcFunc;
 import static android.renderscript.RenderScript.BlendDstFunc;
-
 import android.renderscript.RenderScript;
 import android.renderscript.Element;
 import android.renderscript.Allocation;
+import android.renderscript.ProgramVertexAlloc;
+import static android.renderscript.Element.*;
+
+import static android.util.MathUtils.*;
 
 import java.util.TimeZone;
 
 class GrassRS {
     private static final int RSID_STATE = 0;
+    private static final int RSID_STATE_FRAMECOUNT = 0;
+    private static final int RSID_STATE_BLADES_COUNT = 1;
+
     private static final int RSID_SKY_TEXTURES = 1;
     private static final int SKY_TEXTURES_COUNT = 4;
-
+    
+    private static final int RSID_BLADES = 2;    
+    private static final int BLADES_COUNT = 100;
+    private static final int BLADE_STRUCT_FIELDS_COUNT = 12;
+    private static final int BLADE_STRUCT_DEGREE = 0;
+    private static final int BLADE_STRUCT_SIZE = 1;
+    private static final int BLADE_STRUCT_XPOS = 2;
+    private static final int BLADE_STRUCT_YPOS = 3;
+    private static final int BLADE_STRUCT_OFFSET = 4;
+    private static final int BLADE_STRUCT_SCALE = 5;
+    private static final int BLADE_STRUCT_LENGTHX = 6;
+    private static final int BLADE_STRUCT_LENGTHY = 7;
+    private static final int BLADE_STRUCT_HARDNESS = 8;
+    private static final int BLADE_STRUCT_H = 9;
+    private static final int BLADE_STRUCT_S = 10;
+    private static final int BLADE_STRUCT_B = 11;
+    
     private Resources mResources;
     private RenderScript mRS;
+    
+    private final int mWidth;
+    private final int mHeight;
 
     @SuppressWarnings({"FieldCanBeLocal"})
     private RenderScript.Script mScript;
@@ -46,6 +71,10 @@
     private RenderScript.ProgramFragment mPfBackground;
     @SuppressWarnings({"FieldCanBeLocal"})
     private RenderScript.ProgramFragmentStore mPfsBackground;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private RenderScript.ProgramVertex mPvBackground;    
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private ProgramVertexAlloc mPvOrthoAlloc;
 
     @SuppressWarnings({"FieldCanBeLocal"})
     private Allocation mSkyTexturesIDs;
@@ -55,8 +84,12 @@
     private int[] mSkyBufferIDs;
     @SuppressWarnings({"FieldCanBeLocal"})
     private Allocation mState;
+    @SuppressWarnings({"FieldCanBeLocal"})
+    private Allocation mBlades;
 
-    public GrassRS() {
+    public GrassRS(int width, int height) {
+        mWidth = width;
+        mHeight = height;
     }
 
     public void init(RenderScript rs, Resources res) {
@@ -82,20 +115,46 @@
         loadSkyTextures();
         mScript.bindAllocation(mState, RSID_STATE);
         mScript.bindAllocation(mSkyTexturesIDs, RSID_SKY_TEXTURES);
+        mScript.bindAllocation(mBlades, RSID_BLADES);
 
         mRS.contextBindRootScript(mScript);
     }
 
     private void createScriptStructures() {
-        mState = Allocation.createSized(mRS, Element.USER_I32, 1);
-        mState.data(new int[1]);
+        final int[] data = new int[2];
+        mState = Allocation.createSized(mRS, USER_I32, data.length);
+        data[RSID_STATE_FRAMECOUNT] = 0;
+        data[RSID_STATE_BLADES_COUNT] = BLADES_COUNT;
+        mState.data(data);
+
+        final float[] blades = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
+        mBlades = Allocation.createSized(mRS, USER_FLOAT, blades.length);
+        for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
+            createBlade(blades, i);
+        }
+        mBlades.data(blades);
+    }
+
+    private void createBlade(float[] blades, int index) {
+        //noinspection PointlessArithmeticExpression
+        blades[index + BLADE_STRUCT_DEGREE] = 0.0f;
+        blades[index + BLADE_STRUCT_SIZE] = random(4.0f) + 4.0f;
+        blades[index + BLADE_STRUCT_XPOS] = random(mWidth);
+        blades[index + BLADE_STRUCT_YPOS] = mHeight;
+        blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f;
+        blades[index + BLADE_STRUCT_SCALE] = random(0.6f) + 0.2f;
+        blades[index + BLADE_STRUCT_LENGTHX] = random(4.5f) + 3.0f;
+        blades[index + BLADE_STRUCT_LENGTHY] = random(5.5f) + 2.0f;
+        blades[index + BLADE_STRUCT_HARDNESS] = random(1.0f) + 0.2f;
+        blades[index + BLADE_STRUCT_H] = (51.0f + random(5.0f)) / 255.0f;
+        blades[index + BLADE_STRUCT_S] = (200.0f + random(55.0f)) / 255.0f;
+        blades[index + BLADE_STRUCT_B] = (90.0f + random(165.0f)) / 255.0f;
     }
 
     private void loadSkyTextures() {
         mSkyBufferIDs = new int[SKY_TEXTURES_COUNT];
         mSkyTextures = new Allocation[SKY_TEXTURES_COUNT];
-        mSkyTexturesIDs = Allocation.createSized(
-                mRS, Element.USER_FLOAT, SKY_TEXTURES_COUNT);
+        mSkyTexturesIDs = Allocation.createSized(mRS, USER_FLOAT, SKY_TEXTURES_COUNT);
 
         final Allocation[] textures = mSkyTextures;
         textures[0] = loadTexture(R.drawable.night, "night");
@@ -149,5 +208,13 @@
     }
 
     private void createProgramVertex() {
+        mPvOrthoAlloc = new ProgramVertexAlloc(mRS);
+        mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+
+        mRS.programVertexBegin(null, null);
+        mRS.programVertexSetTextureMatrixEnable(true);
+        mPvBackground = mRS.programVertexCreate();
+        mPvBackground.bindAllocation(0, mPvOrthoAlloc.mAlloc);
+        mPvBackground.setName("PVBackground");
     }
 }
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
index a641e1e..44d5b08 100644
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
@@ -30,7 +30,7 @@
         super.surfaceChanged(holder, format, w, h);
 
         RenderScript RS = createRenderScript();
-        GrassRS render = new GrassRS();
+        GrassRS render = new GrassRS(w, h);
         render.init(RS, getResources());
     }
 }
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 21c9753..e4979ea 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -566,6 +566,59 @@
     glColor4f(r, g, b, a);
 }
 
+static void SC_hsb(float h, float s, float b, float a)
+{
+    float red = 0.0f;
+    float green = 0.0f;
+    float blue = 0.0f;
+    
+    float x = h;
+    float y = s;
+    float z = b;
+    
+    float hf = (x - (int) x) * 6.0f;
+    int ihf = (int) hf;
+    float f = hf - ihf;
+    float pv = z * (1.0f - y);
+    float qv = z * (1.0f - y * f);
+    float tv = z * (1.0f - y * (1.0f - f));
+    
+    switch (ihf) {
+        case 0:         // Red is the dominant color
+            red = z;
+            green = tv;
+            blue = pv;
+            break;
+        case 1:         // Green is the dominant color
+            red = qv;
+            green = z;
+            blue = pv;
+            break;
+        case 2:
+            red = pv;
+            green = z;
+            blue = tv;
+            break;
+        case 3:         // Blue is the dominant color
+            red = pv;
+            green = qv;
+            blue = z;
+            break;
+        case 4:
+            red = tv;
+            green = pv;
+            blue = z;
+            break;
+        case 5:         // Red is the dominant color
+            red = z;
+            green = pv;
+            blue = qv;
+            break;
+    }
+    
+    glColor4f(red, green, blue, a);
+}
+
 /*
 extern "C" void materialDiffuse(float r, float g, float b, float a)
 {
@@ -650,7 +703,7 @@
     { "atanf", (void *)&atanf,
         "float", "(float)" },
     { "atan2f", (void *)&atan2f,
-        "float", "(floatm float)" },
+        "float", "(float, float)" },
     { "fabsf", (void *)&fabsf,
         "float", "(float)" },
     { "randf", (void *)&SC_randf,
@@ -772,6 +825,8 @@
         "void", "(float, float, float, float)" },
     { "color", (void *)&SC_color,
         "void", "(float, float, float, float)" },
+    { "hsb", (void *)&SC_hsb,
+        "void", "(float, float, float, float)" },
 
     { "uploadToTexture", (void *)&SC_uploadToTexture,
         "void", "(int, int)" },
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index ff49c87..5221fed 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -178,6 +178,7 @@
 {
     Mutex::Autolock _l(mLock);
     surface_info_t* info = mInfo;
+    mBuffer.clear(); // free buffer before allocating a new one
     sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
     status_t err = buffer->initCheck();
     if (LIKELY(err == NO_ERROR)) {
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 4036c49..6be372c 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -296,6 +296,19 @@
     // XXX: name not used for now
     HANDLE hMutex;
 
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::Mutex(int type, const char* name)
+{
+    // XXX: type and name not used for now
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
     hMutex = CreateMutex(NULL, FALSE, NULL);
     mState = (void*) hMutex;
 }
@@ -486,7 +499,11 @@
 
 status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
 {
-    return wait(mutex, systemTime()+reltime);
+    WinCondition* condState = (WinCondition*) mState;
+    HANDLE hMutex = (HANDLE) mutex.mState;
+    nsecs_t absTime = systemTime()+reltime;
+
+    return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
 }
 
 /*
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 3a49a5f..c6a9ae8 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -35,6 +35,7 @@
 {
     static {
         System.loadLibrary("media_jni");
+        native_init();
     }
 
     // The field below is accessed by native methods
@@ -211,7 +212,8 @@
      * allocated internally.
      */
     public native void release();
-    private native void native_setup(); 
+    private native void native_setup();
+    private static native void native_init();
 
     private native final void native_finalize();
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index a23f535..a8689f2 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -466,6 +466,7 @@
 
     static {
         System.loadLibrary("media_jni");
+        native_init();
     }
 
     private final static String TAG = "MediaPlayer";
@@ -1109,6 +1110,7 @@
      */
     private native final int native_setMetadataFilter(Parcel request);
 
+    private static native final void native_init();
     private native final void native_setup(Object mediaplayer_this);
     private native final void native_finalize();
 
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index be4b489..46ede7f 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -57,6 +57,7 @@
 {
     static {
         System.loadLibrary("media_jni");
+        native_init();
     }
     private final static String TAG = "MediaRecorder";
 
@@ -655,6 +656,8 @@
      */
     public native void release();
 
+    private static native final void native_init();
+
     private native final void native_setup(Object mediarecorder_this) throws IllegalStateException;
 
     private native final void native_finalize();
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index d5801f7..71af909 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -99,6 +99,7 @@
 {
     static {
         System.loadLibrary("media_jni");
+        native_init();
     }
 
     private final static String TAG = "MediaScanner";
@@ -680,6 +681,26 @@
                 }
                 values.put(MediaStore.MediaColumns.TITLE, title);
             }
+            String album = values.getAsString(Audio.Media.ALBUM);
+            if (MediaFile.UNKNOWN_STRING.equals(album)) {
+                album = values.getAsString(MediaStore.MediaColumns.DATA);
+                // extract last path segment before file name
+                int lastSlash = album.lastIndexOf('/');
+                if (lastSlash >= 0) {
+                    int previousSlash = 0;
+                    while (true) {
+                        int idx = album.indexOf('/', previousSlash + 1);
+                        if (idx < 0 || idx >= lastSlash) {
+                            break;
+                        }
+                        previousSlash = idx;
+                    }
+                    if (previousSlash != 0) {
+                        album = album.substring(previousSlash + 1, lastSlash);
+                        values.put(Audio.Media.ALBUM, album);
+                    }
+                }
+            }
             if (isAudio) {
                 values.put(Audio.Media.IS_RINGTONE, ringtones);
                 values.put(Audio.Media.IS_NOTIFICATION, notifications);
@@ -1404,6 +1425,7 @@
 
     public native byte[] extractAlbumArt(FileDescriptor fd);
 
+    private static native final void native_init();
     private native final void native_setup();
     private native final void native_finalize();
     @Override
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 1f37111..49a82e6 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -12,11 +12,9 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libopencore_player \
-    libopencore_author \
     libomx_amrenc_sharedlibrary \
     libandroid_runtime \
     libnativehelper \
-    libcutils \
     libutils \
     libbinder \
     libmedia \
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
index 51cb6c7..c4dd07e 100644
--- a/media/jni/android_media_AmrInputStream.cpp
+++ b/media/jni/android_media_AmrInputStream.cpp
@@ -169,13 +169,6 @@
 int register_android_media_AmrInputStream(JNIEnv *env)
 {
     const char* const kClassPathName = "android/media/AmrInputStream";
-    jclass clazz;
-
-    clazz = env->FindClass(kClassPathName);
-    if (clazz == NULL) {
-        LOGE("Can't find %s", kClassPathName);
-        return -1;
-    }
 
     return AndroidRuntime::registerNativeMethods(env,
             kClassPathName, gMethods, NELEM(gMethods));
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 4624a18..49f8cdd 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -40,6 +40,7 @@
 
 static fields_t fields;
 static Mutex sLock;
+static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
 
 static void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message)
 {
@@ -269,6 +270,36 @@
     android_media_MediaMetadataRetriever_release(env, thiz);
 }
 
+// This function gets a field ID, which in turn causes class initialization.
+// It is called from a static block in MediaMetadataRetriever, which won't run until the
+// first time an instance of this class is used.
+static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
+{
+    jclass clazz = env->FindClass(kClassPathName);
+    if (clazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaMetadataRetriever");
+        return;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaMetadataRetriever.mNativeContext");
+        return;
+    }
+
+    fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
+    if (fields.bitmapClazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
+        return;
+    }
+
+    fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(IZ[B)V");
+    if (fields.bitmapConstructor == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
+        return;
+    }
+}
+
 static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
 {
     LOGV("native_setup");
@@ -292,36 +323,13 @@
         {"release",         "()V", (void *)android_media_MediaMetadataRetriever_release},
         {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
         {"native_setup",    "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
+        {"native_init",     "()V", (void *)android_media_MediaMetadataRetriever_native_init},
 };
 
-// Register native mehtods with Android runtime environment
+// This function only registers the native methods, and is called from
+// JNI_OnLoad in android_media_MediaPlayer.cpp
 int register_android_media_MediaMetadataRetriever(JNIEnv *env)
 {
-    static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
-    jclass clazz = env->FindClass(kClassPathName);
-    if (clazz == NULL) {
-        LOGE("Can't find class: %s", kClassPathName);
-        return -1;
-    }
-
-    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (fields.context == NULL) {
-        LOGE("Can't find MediaMetadataRetriever.mNativeContext");
-        return -1;
-    }
-
-    fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
-    if (fields.bitmapClazz == NULL) {
-        LOGE("Bitmap class is not found");
-        return -1;
-    }
-
-    fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(IZ[B)V");
-    if (fields.bitmapConstructor == NULL) {
-        LOGE("Bitmap constructor is not found");
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods
-    (env, kClassPathName, nativeMethods, NELEM(nativeMethods));
+        (env, kClassPathName, nativeMethods, NELEM(nativeMethods));
 }
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d26d039..df98de5 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -511,6 +511,51 @@
     return media_player->getMetadata(update_only, apply_filter, metadata) == OK;
 }
 
+// This function gets some field IDs, which in turn causes class initialization.
+// It is called from a static block in MediaPlayer, which won't run until the
+// first time an instance of this class is used.
+static void
+android_media_MediaPlayer_native_init(JNIEnv *env)
+{
+    jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaPlayer");
+    if (clazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaPlayer");
+        return;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mNativeContext");
+        return;
+    }
+
+    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
+                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+    if (fields.post_event == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.postEventFromNative");
+        return;
+    }
+
+    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
+    if (fields.surface == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mSurface");
+        return;
+    }
+
+    jclass surface = env->FindClass("android/view/Surface");
+    if (surface == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/view/Surface");
+        return;
+    }
+
+    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
+    if (fields.surface_native == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface");
+        return;
+    }
+}
 
 static void
 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
@@ -576,53 +621,16 @@
     {"native_invoke",       "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
     {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer_setMetadataFilter},
     {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer_getMetadata},
+    {"native_init",         "()V",                              (void *)android_media_MediaPlayer_native_init},
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
 };
 
 static const char* const kClassPathName = "android/media/MediaPlayer";
 
+// This function only registers the native methods
 static int register_android_media_MediaPlayer(JNIEnv *env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("android/media/MediaPlayer");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MediaPlayer");
-        return -1;
-    }
-
-    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (fields.context == NULL) {
-        LOGE("Can't find MediaPlayer.mNativeContext");
-        return -1;
-    }
-
-    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
-                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
-    if (fields.post_event == NULL) {
-        LOGE("Can't find MediaPlayer.postEventFromNative");
-        return -1;
-    }
-
-    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
-    if (fields.surface == NULL) {
-        LOGE("Can't find MediaPlayer.mSurface");
-        return -1;
-    }
-
-    jclass surface = env->FindClass("android/view/Surface");
-    if (surface == NULL) {
-        LOGE("Can't find android/view/Surface");
-        return -1;
-    }
-
-    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
-    if (fields.surface_native == NULL) {
-        LOGE("Can't find Surface fields");
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 304f521..cad65b3 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -371,6 +371,53 @@
     }
 }
 
+// This function gets some field IDs, which in turn causes class initialization.
+// It is called from a static block in MediaRecorder, which won't run until the
+// first time an instance of this class is used.
+static void
+android_media_MediaRecorder_native_init(JNIEnv *env)
+{
+    jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaRecorder");
+    if (clazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaRecorder");
+        return;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaRecorder.mNativeContext");
+        return;
+    }
+
+    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
+    if (fields.surface == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaRecorder.mSurface");
+        return;
+    }
+
+    jclass surface = env->FindClass("android/view/Surface");
+    if (surface == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/view/Surface");
+        return;
+    }
+
+    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
+    if (fields.surface_native == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface");
+        return;
+    }
+
+    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
+                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+    if (fields.post_event == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "MediaRecorder.postEventFromNative");
+        return;
+    }
+}
+
+
 static void
 android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
 {
@@ -418,55 +465,19 @@
     {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
     {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
     {"stop",                 "()V",                             (void *)android_media_MediaRecorder_stop},
-    {"native_reset",                "()V",                             (void *)android_media_MediaRecorder_native_reset},
+    {"native_reset",         "()V",                             (void *)android_media_MediaRecorder_native_reset},
     {"release",              "()V",                             (void *)android_media_MediaRecorder_release},
+    {"native_init",          "()V",                             (void *)android_media_MediaRecorder_native_init},
     {"native_setup",         "(Ljava/lang/Object;)V",           (void *)android_media_MediaRecorder_native_setup},
     {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
 };
 
 static const char* const kClassPathName = "android/media/MediaRecorder";
 
+// This function only registers the native methods, and is called from
+// JNI_OnLoad in android_media_MediaPlayer.cpp
 int register_android_media_MediaRecorder(JNIEnv *env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("android/media/MediaRecorder");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MediaRecorder");
-        return -1;
-    }
-
-    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (fields.context == NULL) {
-        LOGE("Can't find MediaRecorder.mNativeContext");
-        return -1;
-    }
-
-    fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
-    if (fields.surface == NULL) {
-        LOGE("Can't find MediaRecorder.mSurface");
-        return -1;
-    }
-
-    jclass surface = env->FindClass("android/view/Surface");
-    if (surface == NULL) {
-        LOGE("Can't find android/view/Surface");
-        return -1;
-    }
-
-    fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
-    if (fields.surface_native == NULL) {
-        LOGE("Can't find Surface fields");
-        return -1;
-    }
-
-    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
-                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");
-    if (fields.post_event == NULL) {
-        LOGE("Can't find MediaRecorder.postEventFromNative");
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
                 "android/media/MediaRecorder", gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 8764a70..97de486 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -241,6 +241,27 @@
     return array;
 }
 
+// This function gets a field ID, which in turn causes class initialization.
+// It is called from a static block in MediaScanner, which won't run until the
+// first time an instance of this class is used.
+static void
+android_media_MediaScanner_native_init(JNIEnv *env)
+{
+     jclass clazz;
+
+    clazz = env->FindClass("android/media/MediaScanner");
+    if (clazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaScanner");
+        return;
+    }
+
+    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (fields.context == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaScanner.mNativeContext");
+        return;
+    }
+}
+
 static void
 android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
 {
@@ -275,28 +296,17 @@
                                                         (void *)android_media_MediaScanner_processFile},
     {"setLocale",         "(Ljava/lang/String;)V",      (void *)android_media_MediaScanner_setLocale},
     {"extractAlbumArt",   "(Ljava/io/FileDescriptor;)[B",     (void *)android_media_MediaScanner_extractAlbumArt},
+    {"native_init",        "()V",                      (void *)android_media_MediaScanner_native_init},
     {"native_setup",        "()V",                      (void *)android_media_MediaScanner_native_setup},
     {"native_finalize",     "()V",                      (void *)android_media_MediaScanner_native_finalize},
 };
 
 static const char* const kClassPathName = "android/media/MediaScanner";
 
+// This function only registers the native methods, and is called from
+// JNI_OnLoad in android_media_MediaPlayer.cpp
 int register_android_media_MediaScanner(JNIEnv *env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("android/media/MediaScanner");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MediaScanner");
-        return -1;
-    }
-
-    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (fields.context == NULL) {
-        LOGE("Can't find MediaScanner.mNativeContext");
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
                 "android/media/MediaScanner", gMethods, NELEM(gMethods));
 }
diff --git a/media/jni/android_media_ResampleInputStream.cpp b/media/jni/android_media_ResampleInputStream.cpp
index 0247cdb..f248557 100644
--- a/media/jni/android_media_ResampleInputStream.cpp
+++ b/media/jni/android_media_ResampleInputStream.cpp
@@ -128,13 +128,6 @@
 int register_android_media_ResampleInputStream(JNIEnv *env)
 {
     const char* const kClassPathName = "android/media/ResampleInputStream";
-    jclass clazz;
-
-    clazz = env->FindClass(kClassPathName);
-    if (clazz == NULL) {
-        LOGE("Can't find %s", kClassPathName);
-        return -1;
-    }
 
     return AndroidRuntime::registerNativeMethods(env,
             kClassPathName, gMethods, NELEM(gMethods));
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 1b99d32..70960b5 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -142,6 +142,8 @@
     private final ReentrantLock synthesizerLock = new ReentrantLock();
 
     private static SynthProxy sNativeSynth = null;
+    private static Boolean sIsKillingSynth = true;
+
     @Override
     public void onCreate() {
         super.onCreate();
@@ -152,6 +154,7 @@
         String soLibPath = "/system/lib/libttspico.so";
         if (sNativeSynth == null) {
             sNativeSynth = new SynthProxy(soLibPath);
+            sIsKillingSynth = false;
         }
 
         mSelf = this;
@@ -172,6 +175,9 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
+
+        sIsKillingSynth = true;
+        Log.i("TtsService", "TtsService.onDestroy()");
         // Don't hog the media player
         cleanUpPlayer();
 
@@ -180,6 +186,7 @@
 
         // Unregister all callbacks.
         mCallbacks.kill();
+        //Log.i("TtsService", "TtsService.onDestroy() ended");
     }
 
 
@@ -243,6 +250,9 @@
 
 
     private int setSpeechRate(String callingApp, int rate) {
+        if (sIsKillingSynth) {
+            return TextToSpeech.ERROR;
+        }
         if (isDefaultEnforced()) {
             return sNativeSynth.setSpeechRate(getDefaultRate());
         } else {
@@ -252,23 +262,37 @@
 
 
     private int setPitch(String callingApp, int pitch) {
+        if (sIsKillingSynth) {
+            return TextToSpeech.ERROR;
+        }
         return sNativeSynth.setPitch(pitch);
     }
 
 
     private int isLanguageAvailable(String lang, String country, String variant) {
+        if (sIsKillingSynth) {
+            return TextToSpeech.LANG_NOT_SUPPORTED;
+        }
         //Log.v("TtsService", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")");
         return sNativeSynth.isLanguageAvailable(lang, country, variant);
     }
 
 
     private String[] getLanguage() {
+        if (sIsKillingSynth) {
+            Log.v("TtsService", "killing synth:: aborting getLanguage()");
+            return null;
+        }
         return sNativeSynth.getLanguage();
     }
 
 
     private int setLanguage(String callingApp, String lang, String country, String variant) {
         Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
+        if (sIsKillingSynth) {
+            Log.v("TtsService", "killing synth:: aborting setLanguage()");
+            return TextToSpeech.ERROR;
+        }
         if (isDefaultEnforced()) {
             return sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
                     getDefaultLocVariant());
@@ -402,7 +426,12 @@
                 }
                 if ((mCurrentSpeechItem != null) &&
                      mCurrentSpeechItem.mCallingApp.equals(callingApp)) {
-                    result = sNativeSynth.stop();
+                    if (sIsKillingSynth) {
+                        Log.v("TtsService", "killing synth:: aborting stop()");
+                        result = TextToSpeech.ERROR;
+                    } else {
+                        result = sNativeSynth.stop();
+                    }
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -451,7 +480,12 @@
                 if ((mCurrentSpeechItem != null) &&
                     ((mCurrentSpeechItem.mType != SpeechItem.TEXT_TO_FILE) ||
                       mCurrentSpeechItem.mCallingApp.equals(callingApp))) {
-                    result = sNativeSynth.stop();
+                    if (sIsKillingSynth) {
+                        Log.v("TtsService", "killing synth:: aborting stop()");
+                        result = TextToSpeech.ERROR;
+                    } else {
+                        result = sNativeSynth.stop();
+                    }
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -591,7 +625,9 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        sNativeSynth.speak(speechItem.mText, streamType);
+                        if (!sIsKillingSynth) {
+                            sNativeSynth.speak(speechItem.mText, streamType);
+                        }
                     }
                 } catch (InterruptedException e) {
                     Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted");
@@ -660,7 +696,9 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
+                        if (!sIsKillingSynth) {
+                            sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
+                        }
                     }
                 } catch (InterruptedException e) {
                     Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted");
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index b107c7d..f410c7b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -147,8 +147,7 @@
 
     synchronized boolean onConnect(String username, String password) {
         try {
-            mState = VpnState.CONNECTING;
-            broadcastConnectivity(VpnState.CONNECTING);
+            setState(VpnState.CONNECTING);
 
             stopPreviouslyRunDaemons();
             String serverIp = getIp(getProfile().getServerName());
@@ -166,8 +165,7 @@
     synchronized void onDisconnect() {
         try {
             Log.i(TAG, "disconnecting VPN...");
-            mState = VpnState.DISCONNECTING;
-            broadcastConnectivity(VpnState.DISCONNECTING);
+            setState(VpnState.DISCONNECTING);
             mNotification.showDisconnect();
 
             mDaemonHelper.stopAll();
@@ -235,14 +233,13 @@
         saveOriginalDns();
         saveAndSetDomainSuffices();
 
-        mState = VpnState.CONNECTED;
         mStartTime = System.currentTimeMillis();
 
         // set DNS after saving the states in case the process gets killed
         // before states are saved
         saveSelf();
         setVpnDns();
-        broadcastConnectivity(VpnState.CONNECTED);
+        setState(VpnState.CONNECTED);
 
         enterConnectivityLoop();
     }
@@ -261,10 +258,10 @@
 
         restoreOriginalDns();
         restoreOriginalDomainSuffices();
-        mState = VpnState.IDLE;
-        broadcastConnectivity(VpnState.IDLE);
+        setState(VpnState.IDLE);
 
         // stop the service itself
+        SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
         mContext.removeStates();
         mContext.stopSelf();
     }
@@ -316,6 +313,11 @@
         SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
     }
 
+    private void setState(VpnState newState) {
+        mState = newState;
+        broadcastConnectivity(newState);
+    }
+
     private void broadcastConnectivity(VpnState s) {
         VpnManager m = new VpnManager(mContext);
         Throwable err = mError;
@@ -326,6 +328,9 @@
             } else if (err instanceof VpnConnectingError) {
                 m.broadcastConnectivity(mProfile.getName(), s,
                         ((VpnConnectingError) err).getErrorCode());
+            } else if (VPN_IS_UP.equals(SystemProperties.get(VPN_STATUS))) {
+                m.broadcastConnectivity(mProfile.getName(), s,
+                        VpnManager.VPN_ERROR_CONNECTION_LOST);
             } else {
                 m.broadcastConnectivity(mProfile.getName(), s,
                         VpnManager.VPN_ERROR_CONNECTION_FAILED);
@@ -373,7 +378,7 @@
     // returns false if vpn connectivity is broken
     private boolean checkConnectivity() {
         if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
-            onDisconnect();
+            onError(new IOException("Connectivity lost"));
             return false;
         } else {
             return true;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index a3c3436..447e9fa 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -765,15 +765,17 @@
         switch (type)
         {
             case PowerManager.FULL_WAKE_LOCK:
-                return "FULL_WAKE_LOCK         ";
+                return "FULL_WAKE_LOCK                ";
             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                return "SCREEN_BRIGHT_WAKE_LOCK";
+                return "SCREEN_BRIGHT_WAKE_LOCK       ";
             case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                return "SCREEN_DIM_WAKE_LOCK   ";
+                return "SCREEN_DIM_WAKE_LOCK          ";
             case PowerManager.PARTIAL_WAKE_LOCK:
-                return "PARTIAL_WAKE_LOCK      ";
+                return "PARTIAL_WAKE_LOCK             ";
+            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
             default:
-                return "???                    ";
+                return "???                           ";
         }
     }
 
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 5aed396..e71d3291 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -375,7 +375,8 @@
             else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
                 onBatteryLow(intent);
             }
-            else if (action.equals(Intent.ACTION_BATTERY_OKAY)) {
+            else if (action.equals(Intent.ACTION_BATTERY_OKAY)
+                    || action.equals(Intent.ACTION_POWER_CONNECTED)) {
                 onBatteryOkay(intent);
             }
             else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) ||
@@ -523,6 +524,7 @@
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Intent.ACTION_BATTERY_LOW);
         filter.addAction(Intent.ACTION_BATTERY_OKAY);
+        filter.addAction(Intent.ACTION_POWER_CONNECTED);
         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
         filter.addAction(Intent.ACTION_ALARM_CHANGED);
         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
diff --git a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
index 44958e9..4b88057 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
@@ -35,7 +35,12 @@
     static public final int IS95_CONST_IR_ALERT_MED = 0;
     static public final int IS95_CONST_IR_ALERT_HIGH = 1;
     static public final int IS95_CONST_IR_ALERT_LOW = 2;
-    static public final int TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN = 255;
+
+    // Based on 3GPP2 C.S0005-E, seciton 3.7.5.5 Signal,
+    // set TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN to 0 to avoid
+    // the alert pitch to be involved in hash calculation for
+    // signal type other than IS54B.
+    static public final int TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN = 0;
 
     // public final int int IS95_CONST_IR_SIGNAL_TYPE;
     static public final int IS95_CONST_IR_SIG_ISDN_NORMAL = 0;
@@ -81,6 +86,15 @@
                 (alertPitch < 0) || (signal > 256) || (signal < 0)) {
             return new Integer(CDMA_INVALID_TONE);
         }
+        // Based on 3GPP2 C.S0005-E, seciton 3.7.5.5 Signal,
+        // the alert pitch field is ignored by the mobile station unless
+        // SIGNAL_TYPE is '10',IS-54B Alerting.
+        // Set alert pitch to TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN
+        // so the alert pitch is not involved in hash calculation
+        // when signal type is not IS-54B.
+        if (signalType != IS95_CONST_IR_SIGNAL_IS54B) {
+            alertPitch = TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN;
+        }
         return new Integer(signalType * 256 * 256 + alertPitch * 256 + signal);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index c71003b..d4ec85a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -853,7 +853,7 @@
         }
     }
 
-    private static String decodeIa5(byte[] data, int offset, int numFields)
+    private static String decode7bitAscii(byte[] data, int offset, int numFields)
         throws CodingException
     {
         try {
@@ -868,38 +868,20 @@
             inStream.skip(offset);
             for (int i = 0; i < numFields; i++) {
                 int charCode = inStream.read(7);
-                if ((charCode < UserData.IA5_MAP_BASE_INDEX) ||
-                        (charCode > UserData.IA5_MAP_MAX_INDEX)) {
-                    throw new CodingException("unsupported AI5 character code (" + charCode + ")");
+                if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) ||
+                        (charCode <= UserData.ASCII_MAP_MAX_INDEX)) {
+                    strBuf.append(UserData.ASCII_MAP[charCode - UserData.ASCII_MAP_BASE_INDEX]);
+                } else if (charCode == UserData.ASCII_LF_INDEX) {
+                    strBuf.append('\r');
+                } else if (charCode == UserData.ASCII_CR_INDEX) {
+                    strBuf.append('\n');
+                } else {
+                    /* For other charCodes, they are unprintable, and so simply use SPACE. */
+                    strBuf.append(' ');
                 }
-                strBuf.append(UserData.IA5_MAP[charCode - UserData.IA5_MAP_BASE_INDEX]);
             }
             return strBuf.toString();
         } catch (BitwiseInputStream.AccessException ex) {
-            throw new CodingException("AI5 decode failed: " + ex);
-        }
-    }
-
-    private static String decode7bitAscii(byte[] data, int offset, int numFields)
-        throws CodingException
-    {
-        try {
-            offset *= 8;
-            BitwiseInputStream inStream = new BitwiseInputStream(data);
-            int wantedBits = offset + (numFields * 7);
-            if (inStream.available() < wantedBits) {
-                throw new CodingException("insufficient data (wanted " + wantedBits +
-                                          " bits, but only have " + inStream.available() + ")");
-            }
-            inStream.skip(offset);
-            byte[] expandedData = new byte[numFields];
-            for (int i = 0; i < numFields; i++) {
-                expandedData[i] = (byte)inStream.read(7);
-            }
-            return new String(expandedData, 0, numFields, "US-ASCII");
-        } catch (java.io.UnsupportedEncodingException ex) {
-            throw new CodingException("7bit ASCII decode failed: " + ex);
-        } catch (BitwiseInputStream.AccessException ex) {
             throw new CodingException("7bit ASCII decode failed: " + ex);
         }
     }
@@ -956,12 +938,10 @@
             // octet encoded.
             userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
             break;
+        case UserData.ENCODING_IA5:
         case UserData.ENCODING_7BIT_ASCII:
             userData.payloadStr = decode7bitAscii(userData.payload, offset, userData.numFields);
             break;
-        case UserData.ENCODING_IA5:
-            userData.payloadStr = decodeIa5(userData.payload, offset, userData.numFields);
-            break;
         case UserData.ENCODING_UNICODE_16:
             userData.payloadStr = decodeUtf16(userData.payload, offset, userData.numFields);
             break;
@@ -1003,7 +983,7 @@
         try {
             StringBuffer strbuf = new StringBuffer(dataLen);
             while (inStream.available() >= 6) {
-                strbuf.append(UserData.IA5_MAP[inStream.read(6)]);
+                strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
             }
             String data = strbuf.toString();
             bData.numberOfMessages = Integer.parseInt(data.substring(0, 2));
@@ -1045,7 +1025,7 @@
         }
         StringBuffer strbuf = new StringBuffer(dataLen);
         for (int i = 0; i < numFields; i++) {
-            strbuf.append(UserData.IA5_MAP[inStream.read(6)]);
+            strbuf.append(UserData.ASCII_MAP[inStream.read(6)]);
         }
         bData.userData.payloadStr = strbuf.toString();
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index 54c1f80..15cb5e4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -49,19 +49,20 @@
     public static final int IS91_MSG_TYPE_SHORT_MESSAGE      = 0x85;
 
     /**
-     * IA5 data encoding character mappings.
-     * (See CCITT Rec. T.50 Tables 1 and 3)
+     * US ASCII character mapping table.
      *
-     * Note this mapping is the the same as for printable ASCII
-     * characters, with a 0x20 offset, meaning that the ASCII SPACE
-     * character occurs with code 0x20.
+     * This table contains only the printable ASCII characters, with a
+     * 0x20 offset, meaning that the ASCII SPACE character is at index
+     * 0, with the resulting code of 0x20.
      *
-     * Note this mapping is also equivalent to that used by the IS-91
-     * protocol, except for the latter using only 6 bits, and hence
-     * mapping only entries up to the '_' character.
+     * Note this mapping is also equivalent to that used by both the
+     * IS5 and the IS-91 encodings.  For the former this is defined
+     * using CCITT Rec. T.50 Tables 1 and 3.  For the latter IS 637 B,
+     * Table 4.3.1.4.1-1 -- and note the encoding uses only 6 bits,
+     * and hence only maps entries up to the '_' character.
      *
      */
-    public static final char[] IA5_MAP = {
+    public static final char[] ASCII_MAP = {
         ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
         '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
@@ -85,8 +86,8 @@
     public static final int ASCII_CR_INDEX = 0x0D;
     public static final SparseIntArray charToAscii = new SparseIntArray();
     static {
-        for (int i = 0; i < IA5_MAP.length; i++) {
-            charToAscii.put(IA5_MAP[i], PRINTABLE_ASCII_MIN_INDEX + i);
+        for (int i = 0; i < ASCII_MAP.length; i++) {
+            charToAscii.put(ASCII_MAP[i], PRINTABLE_ASCII_MIN_INDEX + i);
         }
         charToAscii.put('\r', ASCII_LF_INDEX);
         charToAscii.put('\n', ASCII_CR_INDEX);
@@ -113,11 +114,11 @@
     }
 
     /**
-     * Mapping for IA5 values less than 32 are flow control signals
+     * Mapping for ASCII values less than 32 are flow control signals
      * and not used here.
      */
-    public static final int IA5_MAP_BASE_INDEX = 0x20;
-    public static final int IA5_MAP_MAX_INDEX = IA5_MAP_BASE_INDEX + IA5_MAP.length - 1;
+    public static final int ASCII_MAP_BASE_INDEX = 0x20;
+    public static final int ASCII_MAP_MAX_INDEX = ASCII_MAP_BASE_INDEX + ASCII_MAP.length - 1;
 
     /**
      * Contains the data header of the user data
diff --git a/tests/CoreTests/android/core/TestEventHandler.java b/tests/CoreTests/android/core/TestEventHandler.java
index 4cfcade..45f2f69 100644
--- a/tests/CoreTests/android/core/TestEventHandler.java
+++ b/tests/CoreTests/android/core/TestEventHandler.java
@@ -497,7 +497,7 @@
      * SSL certificate error callback. Handles SSL error(s) on the way
      * up to the user.
      */
-    public void handleSslErrorRequest(SslError error) {
+    public boolean handleSslErrorRequest(SslError error) {
       int primaryError = error.getPrimaryError();
 
       if (Config.LOGV) {
@@ -527,6 +527,9 @@
 
       if (expectSslErrors == -1) // && expectSslCertificate == certificate?
         expects[TEST_SSL_CERTIFICATE_ERROR] = false;
+
+      // return false so that we won't block the thread
+      return false;
     }
 
     /**
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index de39800..71d9758 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -1,5 +1,7 @@
 package com.android.dumprendertree;
 
+import android.app.Activity;
+import android.content.Intent;
 import android.os.Handler;
 import android.os.Message;
 import android.test.ActivityInstrumentationTestCase2;
@@ -33,7 +35,7 @@
     }
 
     public void runReliabilityTest() throws Throwable {
-        ReliabilityTestActivity activity = getActivity();
+//        ReliabilityTestActivity activity = getActivity();
         LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner)getInstrumentation();
 
         File testListFile = new File(TEST_LIST_FILE);
@@ -54,6 +56,8 @@
         boolean timeoutFlag = false;
         long start, elapsed;
 
+        Intent intent = new Intent(runner.getContext(), ReliabilityTestActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         //read from BufferedReader instead of populating a list in advance,
         //this will avoid excessive memory usage in case of a large list
         while((url = listReader.readLine()) != null) {
@@ -63,6 +67,8 @@
             start = System.currentTimeMillis();
             Log.v(LOGTAG, "Testing URL: " + url);
             FsUtils.updateTestStatus(TEST_STATUS_FILE, url);
+            ReliabilityTestActivity activity = (ReliabilityTestActivity)runner.startActivitySync(
+                    intent);
             activity.reset();
             //use message to send new URL to avoid interacting with
             //WebView in non-UI thread
@@ -88,12 +94,13 @@
             if(runner.mLogtime) {
                 writeLoadTime(url, activity.getPageLoadTime());
             }
+            activity.finish();
             System.runFinalization();
             System.gc();
             System.gc();
         }
         FsUtils.updateTestStatus(TEST_STATUS_FILE, TEST_DONE);
-        activity.finish();
+//        activity.finish();
         listReader.close();
     }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index 5ddd0b3..db40daf 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -122,8 +122,9 @@
 
     @Override
     protected void onDestroy() {
-        Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
         super.onDestroy();
+        Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
+        webView.destroy();
     }
 
     private boolean isPageDone() {
@@ -270,8 +271,7 @@
         }
 
         public void run() {
-            if (initialStartCount == pageStartCount) {
-                //perform cleanup
+            if (initialStartCount == pageStartCount && !isPageDone()) {
                 handler.removeMessages(MSG_TIMEOUT);
                 webView.stopLoading();
                 handler.postDelayed(pageDoneRunner, manualDelay);
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index e448e5a..f71bbea 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -54,6 +54,8 @@
     public static final int VPN_ERROR_CHALLENGE = 4;
     /** Error code to indicate an error of remote server hanging up. */
     public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
+    /** Error code to indicate an error of losing connectivity. */
+    public static final int VPN_ERROR_CONNECTION_LOST = 6;
     private static final int VPN_ERROR_NO_ERROR = 0;
 
     public static final String PROFILES_PATH = "/data/misc/vpn/profiles";