Merge change 25362 into eclair

* changes:
  Handle BACK key with focus in search ACTV correctly
diff --git a/api/current.xml b/api/current.xml
index 6174bff..448da7c 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -27401,6 +27401,87 @@
 >
 </method>
 </class>
+<class name="ParcelUuid"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="ParcelUuid"
+ type="android.bluetooth.ParcelUuid"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="fromString"
+ return="android.bluetooth.ParcelUuid"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.lang.String">
+</parameter>
+</method>
+<method name="getUuid"
+ return="java.util.UUID"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 </package>
 <package name="android.content"
 >
@@ -35178,6 +35259,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_DOCK_EVENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.DOCK_EVENT&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_EDIT"
  type="java.lang.String"
  transient="false"
@@ -35893,6 +35985,17 @@
  visibility="public"
 >
 </field>
+<field name="CATEGORY_CAR_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.category.CAR_DOCK&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CATEGORY_DEFAULT"
  type="java.lang.String"
  transient="false"
@@ -35904,6 +36007,17 @@
  visibility="public"
 >
 </field>
+<field name="CATEGORY_DESK_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.category.DESK_DOCK&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CATEGORY_DEVELOPMENT_PREFERENCE"
  type="java.lang.String"
  transient="false"
@@ -36123,6 +36237,50 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_DOCK_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.DOCK_STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_CAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_DESK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_UNDOCKED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_DONT_KILL_APP"
  type="java.lang.String"
  transient="false"
@@ -43786,6 +43944,39 @@
  visibility="public"
 >
 </field>
+<field name="NAVIGATIONHIDDEN_NO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATIONHIDDEN_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATIONHIDDEN_YES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NAVIGATION_DPAD"
  type="int"
  transient="false"
@@ -44108,6 +44299,16 @@
  visibility="public"
 >
 </field>
+<field name="navigationHidden"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="orientation"
  type="int"
  transient="false"
@@ -66956,6 +67157,17 @@
 <parameter name="cb" type="android.hardware.Camera.AutoFocusCallback">
 </parameter>
 </method>
+<method name="cancelAutoFocus"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getParameters"
  return="android.hardware.Camera.Parameters"
  abstract="false"
@@ -77314,6 +77526,387 @@
 </parameter>
 </method>
 </interface>
+<class name="ExifInterface"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ExifInterface"
+ type="android.media.ExifInterface"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filename" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</constructor>
+<method name="getAttribute"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDateTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLatLong"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOrientationString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getThumbnail"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWhiteBalanceString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasThumbnail"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="saveAttributes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="setAttribute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<field name="ORIENTATION_FLIP_HORIZONTAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_FLIP_VERTICAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_180"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_270"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_90"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_TRANSPOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_TRANSVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_DATETIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;DateTime&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_FLASH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;Flash&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LATITUDE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSLatitude&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LATITUDE_REF"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSLatitudeRef&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LONGITUDE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSLongitude&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LONGITUDE_REF"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;GPSLongitudeRef&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_IMAGE_LENGTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ImageLength&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_IMAGE_WIDTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ImageWidth&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_MAKE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;Make&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_MODEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;Model&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_ORIENTATION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;Orientation&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_WHITE_BALANCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;WhiteBalance&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WHITEBALANCE_AUTO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WHITEBALANCE_MANUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="FaceDetector"
  extends="java.lang.Object"
  abstract="false"
@@ -128851,6 +129444,17 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_TEXT_FLAG_NO_SUGGESTIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="524288"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TYPE_TEXT_VARIATION_EMAIL_ADDRESS"
  type="int"
  transient="false"
@@ -159360,6 +159964,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_TURN_SCREEN_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2097152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_WATCH_OUTSIDE_TOUCH"
  type="int"
  transient="false"
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 83c7871..87fdc80 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -116,10 +116,13 @@
 
 static int is_alnum_string(char *s)
 {
+    char *s0 = s;
     while (*s != 0) {
-        if (!isalnum(*s++)) return 0;
+        if (!isalnum(*s++)) {
+            LOGE("The string '%s' is not an alphanumeric string\n", s0);
+            return 0;
+        }
     }
-    LOGE("The string %s is not an alphanumeric string\n", s);
     return 1;
 }
 
@@ -159,7 +162,9 @@
 // no argument
 static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
 {
-    reply->retcode = get_state();
+    int s = get_state();
+    if (DBG) LOGD("keystore state = %d\n", s);
+    reply->retcode = s;
 }
 
 // args of listkeys():
@@ -413,12 +418,10 @@
 
         // read the command, execute and send the result back.
         if(read_marshal(s, &cmd)) goto err;
-        if (DBG) LOGD("new connection\n");
         execute(&cmd, &reply);
         write_marshal(s, &reply);
 err:
         memset(&reply, 0, sizeof(LPC_MARSHAL));
-        if (DBG) LOGD("closing connection\n");
         close(s);
     }
 
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index c13893a..4217957 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -46,7 +46,6 @@
 import android.app.PendingIntent;
 import android.app.NotificationManager;
 import android.app.Notification;
-import android.app.Activity;
 import android.Manifest;
 
 import java.io.FileDescriptor;
@@ -471,6 +470,7 @@
     }
 
     private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) {
+        cancelNotification(getSigninRequiredNotificationId(account));
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
@@ -523,7 +523,7 @@
         checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
         try {
-            cacheAuthToken(account, authTokenType, authToken);
+            saveAuthTokenToDatabase(account, authTokenType, authToken);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -686,7 +686,8 @@
                                         "the type and name should not be empty");
                                 return;
                             }
-                            cacheAuthToken(new Account(name, type), authTokenType, authToken);
+                            saveAuthTokenToDatabase(new Account(name, type),
+                                    authTokenType, authToken);
                         }
 
                         Intent intent = result.getParcelable(Constants.INTENT_KEY);
@@ -714,11 +715,14 @@
 
         Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
                 0 /* when */);
-        final CharSequence subtitleFormatString =
-                mContext.getText(R.string.permission_request_notification_subtitle);
+        final String titleAndSubtitle =
+                mContext.getString(R.string.permission_request_notification_with_subtitle,
+                account.name);
+        final int index = titleAndSubtitle.indexOf('\n');
+        final String title = titleAndSubtitle.substring(0, index);
+        final String subtitle = titleAndSubtitle.substring(index + 1);
         n.setLatestEventInfo(mContext,
-                mContext.getText(R.string.permission_request_notification_title),
-                String.format(subtitleFormatString.toString(), account.name),
+                title, subtitle,
                 PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
         ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
                 .notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
@@ -1001,10 +1005,6 @@
         }
     }
 
-    private boolean cacheAuthToken(Account account, String authTokenType, String authToken) {
-        return saveAuthTokenToDatabase(account, authTokenType, authToken);
-    }
-
     private long getAccountId(SQLiteDatabase db, Account account) {
         Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
                 "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 8f7e8ca..4f9531e 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,14 +20,15 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContentResolver.OpenResourceIdResult;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.DrawableContainer;
 import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -38,14 +39,15 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Filter;
 import android.widget.ImageView;
 import android.widget.ResourceCursorAdapter;
 import android.widget.TextView;
-import android.widget.Filter;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.List;
 import java.util.WeakHashMap;
 
 /**
@@ -580,14 +582,26 @@
             // Not cached, try using it as a plain resource ID in the provider's context.
             int resourceId = Integer.parseInt(drawableId);
             drawable = mProviderContext.getResources().getDrawable(resourceId);
-            if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId);
         } catch (NumberFormatException nfe) {
-            // The id was not an integer resource id.
-            // Let the ContentResolver handle content, android.resource and file URIs.
+            // The id was not an integer resource id, use it as a URI
             try {
                 Uri uri = Uri.parse(drawableId);
-                InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
-                if (stream != null) {
+                String scheme = uri.getScheme();
+                if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+                    // Load drawables through Resources, to get the source density information
+                    OpenResourceIdResult r =
+                            mProviderContext.getContentResolver().getResourceId(uri);
+                    try {
+                        drawable = r.r.getDrawable(r.id);
+                    } catch (Resources.NotFoundException ex) {
+                        throw new FileNotFoundException("Resource does not exist: " + uri);
+                    }
+                } else {
+                    // Let the ContentResolver handle content and file URIs.
+                    InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+                    if (stream == null) {
+                        throw new FileNotFoundException("Failed to open " + uri);
+                    }
                     try {
                         drawable = Drawable.createFromStream(stream, null);
                     } finally {
@@ -598,22 +612,25 @@
                         }
                     }
                 }
-                if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId);
             } catch (FileNotFoundException fnfe) {
-                if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId);
+                Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
                 // drawable = null;
             }
-
-            // If we got a drawable for this resource id, then stick it in the
-            // map so we don't do this lookup again.
-            if (drawable != null) {
-                mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
-            }
         } catch (Resources.NotFoundException nfe) {
-            if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
+            Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
             // drawable = null;
         }
 
+        if (drawable == null) {
+            if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
+        } else {
+            if (DBG) {
+                Log.d(LOG_TAG, "Found icon: " + drawableId);
+            }
+            // Cache it so we don't do this lookup again
+            mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+        }
+
         return drawable;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index b1861ac..0b3f3c7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -503,7 +503,7 @@
     }
 
     /** @hide */
-     public String[] getUuids() {
+     public ParcelUuid[] getUuids() {
         try {
             return sService.getRemoteUuids(mAddress);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -511,7 +511,7 @@
     }
 
     /** @hide */
-    public int getServiceChannel(String uuid) {
+    public int getServiceChannel(ParcelUuid uuid) {
          try {
              return sService.getRemoteServiceChannel(mAddress, uuid);
          } catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index c15bc20..409c744 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -16,10 +16,11 @@
 
 package android.bluetooth;
 
-import java.util.UUID;
+import java.util.Arrays;
+import java.util.HashSet;
 
 /**
-* Static helper methods and constants to decode the UUID of remote devices.
+* Static helper methods and constants to decode the ParcelUuid of remote devices.
 *  @hide
 */
 public final class BluetoothUuid {
@@ -30,40 +31,99 @@
      * The following 128 bit values are calculated as:
      *  uuid * 2^96 + BASE_UUID
      */
-    public static final UUID AudioSink = UUID.fromString("0000110B-0000-1000-8000-00805F9B34FB");
-    public static final UUID AudioSource = UUID.fromString("0000110A-0000-1000-8000-00805F9B34FB");
-    public static final UUID AdvAudioDist = UUID.fromString("0000110D-0000-1000-8000-00805F9B34FB");
-    public static final UUID HSP       = UUID.fromString("00001108-0000-1000-8000-00805F9B34FB");
-    public static final UUID Handsfree  = UUID.fromString("0000111E-0000-1000-8000-00805F9B34FB");
-    public static final UUID AvrcpController =
-                                          UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
-    public static final UUID AvrcpTarget = UUID.fromString("0000110C-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid AudioSink =
+            ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid AudioSource =
+            ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid AdvAudioDist =
+            ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid HSP =
+            ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid Handsfree =
+            ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid AvrcpController =
+            ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid AvrcpTarget =
+            ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
+    public static final ParcelUuid ObexObjectPush =
+            ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
 
-    public static boolean isAudioSource(UUID uuid) {
+    public static boolean isAudioSource(ParcelUuid uuid) {
         return uuid.equals(AudioSource);
     }
 
-    public static boolean isAudioSink(UUID uuid) {
+    public static boolean isAudioSink(ParcelUuid uuid) {
         return uuid.equals(AudioSink);
     }
 
-    public static boolean isAdvAudioDist(UUID uuid) {
+    public static boolean isAdvAudioDist(ParcelUuid uuid) {
         return uuid.equals(AdvAudioDist);
     }
 
-    public static boolean isHandsfree(UUID uuid) {
+    public static boolean isHandsfree(ParcelUuid uuid) {
         return uuid.equals(Handsfree);
     }
 
-    public static boolean isHeadset(UUID uuid) {
+    public static boolean isHeadset(ParcelUuid uuid) {
         return uuid.equals(HSP);
     }
 
-    public static boolean isAvrcpController(UUID uuid) {
+    public static boolean isAvrcpController(ParcelUuid uuid) {
         return uuid.equals(AvrcpController);
     }
 
-    public static boolean isAvrcpTarget(UUID uuid) {
+    public static boolean isAvrcpTarget(ParcelUuid uuid) {
         return uuid.equals(AvrcpTarget);
     }
+
+    /**
+     * Returns true if ParcelUuid is present in uuidArray
+     *
+     * @param uuidArray - Array of ParcelUuids
+     * @param uuid
+     */
+    public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) {
+        for (ParcelUuid element: uuidArray) {
+            if (element.equals(uuid)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if there any common ParcelUuids in uuidA and uuidB.
+     *
+     * @param uuidA - List of ParcelUuids
+     * @param uuidB - List of ParcelUuids
+     *
+     */
+    public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
+        if (uuidA == null && uuidB == null) return true;
+        if (uuidA == null || uuidB == null) return false;
+
+        HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
+        for (ParcelUuid uuid: uuidB) {
+            if (uuidSet.contains(uuid)) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if all the ParcelUuids in ParcelUuidB are present in
+     * ParcelUuidA
+     *
+     * @param uuidA - Array of ParcelUuidsA
+     * @param uuidB - Array of ParcelUuidsB
+     *
+     */
+    public static boolean containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
+        if (uuidA == null && uuidB == null) return true;
+        if (uuidA == null || uuidB == null) return false;
+
+        HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
+        for (ParcelUuid uuid: uuidB) {
+            if (!uuidSet.contains(uuid)) return false;
+        }
+        return true;
+    }
+
 }
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index a11ceac..04c8ec9 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -16,6 +16,8 @@
 
 package android.bluetooth;
 
+import android.bluetooth.ParcelUuid;
+
 /**
  * System private API for talking with the Bluetooth service.
  *
@@ -50,8 +52,8 @@
 
     String getRemoteName(in String address);
     int getRemoteClass(in String address);
-    String[] getRemoteUuids(in String address);
-    int getRemoteServiceChannel(in String address, String uuid);
+    ParcelUuid[] getRemoteUuids(in String address);
+    int getRemoteServiceChannel(in String address,in ParcelUuid uuid);
 
     boolean setPin(in String address, in byte[] pin);
     boolean setPasskey(in String address, int passkey);
diff --git a/core/java/android/bluetooth/ParcelUuid.aidl b/core/java/android/bluetooth/ParcelUuid.aidl
new file mode 100644
index 0000000..70bcc4b
--- /dev/null
+++ b/core/java/android/bluetooth/ParcelUuid.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable ParcelUuid;
diff --git a/core/java/android/bluetooth/ParcelUuid.java b/core/java/android/bluetooth/ParcelUuid.java
new file mode 100644
index 0000000..27166a0
--- /dev/null
+++ b/core/java/android/bluetooth/ParcelUuid.java
@@ -0,0 +1,135 @@
+/*
+ * 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.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.UUID;
+
+/**
+ * This class is a Parcelable wrapper around {@link UUID} which is an
+ * immutable representation of a 128-bit universally unique
+ * identifier.
+ */
+public final class ParcelUuid implements Parcelable {
+
+    private final UUID mUuid;
+
+    /**
+     * Constructor creates a ParcelUuid instance from the
+     * given {@link UUID}.
+     *
+     * @param uuid UUID
+     */
+    public ParcelUuid(UUID uuid) {
+        mUuid = uuid;
+    }
+
+    /**
+     * Creates a new ParcelUuid from a string representation of {@link UUID}.
+     *
+     * @param uuid
+     *            the UUID string to parse.
+     * @return an ParcelUuid instance.
+     * @throws NullPointerException
+     *             if {@code uuid} is {@code null}.
+     * @throws IllegalArgumentException
+     *             if {@code uuid} is not formatted correctly.
+     */
+    public static ParcelUuid fromString(String uuid) {
+        return new ParcelUuid(UUID.fromString(uuid));
+    }
+
+    /**
+     * Get the {@link UUID} represented by the ParcelUuid.
+     *
+     * @return UUID contained in the ParcelUuid.
+     */
+    public UUID getUuid() {
+        return mUuid;
+    }
+
+    /**
+     * Returns a string representation of the ParcelUuid
+     * For example: 0000110B-0000-1000-8000-00805F9B34FB will be the return value.
+     *
+     * @return a String instance.
+     */
+    @Override
+    public String toString() {
+        return mUuid.toString();
+    }
+
+
+   @Override
+   public int hashCode() {
+       return mUuid.hashCode();
+   }
+
+   /**
+    * Compares this ParcelUuid to another object for equality. If {@code object}
+    * is not {@code null}, is a ParcelUuid instance, and all bits are equal, then
+    * {@code true} is returned.
+    *
+    * @param object
+    *            the {@code Object} to compare to.
+    * @return {@code true} if this ParcelUuid is equal to {@code object}
+    *         or {@code false} if not.
+    */
+   @Override
+   public boolean equals(Object object) {
+       if (object == null) {
+           return false;
+       }
+
+       if (this == object) {
+           return true;
+       }
+
+       if (!(object instanceof ParcelUuid)) {
+           return false;
+       }
+
+       ParcelUuid that = (ParcelUuid) object;
+
+       return (this.mUuid.equals(that.mUuid));
+   }
+
+   public static final Parcelable.Creator<ParcelUuid> CREATOR =
+               new Parcelable.Creator<ParcelUuid>() {
+        public ParcelUuid createFromParcel(Parcel source) {
+            long mostSigBits = source.readLong();
+            long leastSigBits = source.readLong();
+            UUID uuid = new UUID(mostSigBits, leastSigBits);
+            return new ParcelUuid(uuid);
+        }
+
+        public ParcelUuid[] newArray(int size) {
+            return new ParcelUuid[size];
+        }
+    };
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(mUuid.getMostSignificantBits());
+        dest.writeLong(mUuid.getLeastSignificantBits());
+    }
+}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 238792b..60b406d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -221,26 +221,30 @@
         } else if (mType == TYPE_UPDATE) {
             numRows = provider.update(mUri, values, mSelection, selectionArgs);
         } else if (mType == TYPE_ASSERT) {
-            // Build projection map from expected values
-            final ArrayList<String> projectionList = new ArrayList<String>();
-            for (Map.Entry<String, Object> entry : values.valueSet()) {
-                projectionList.add(entry.getKey());
-            }
-
             // Assert that all rows match expected values
-            final String[] projection = projectionList.toArray(new String[projectionList.size()]);
+            String[] projection =  null;
+            if (values != null) {
+                // Build projection map from expected values
+                final ArrayList<String> projectionList = new ArrayList<String>();
+                for (Map.Entry<String, Object> entry : values.valueSet()) {
+                    projectionList.add(entry.getKey());
+                }
+                projection = projectionList.toArray(new String[projectionList.size()]);
+            }
             final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null);
-            numRows = cursor.getCount();
             try {
-                while (cursor.moveToNext()) {
-                    for (int i = 0; i < projection.length; i++) {
-                        final String cursorValue = cursor.getString(i);
-                        final String expectedValue = values.getAsString(projection[i]);
-                        if (!TextUtils.equals(cursorValue, expectedValue)) {
-                            // Throw exception when expected values don't match
-                            throw new OperationApplicationException("Found value " + cursorValue
-                                    + " when expected " + expectedValue + " for column "
-                                    + projection[i]);
+                numRows = cursor.getCount();
+                if (projection != null) {
+                    while (cursor.moveToNext()) {
+                        for (int i = 0; i < projection.length; i++) {
+                            final String cursorValue = cursor.getString(i);
+                            final String expectedValue = values.getAsString(projection[i]);
+                            if (!TextUtils.equals(cursorValue, expectedValue)) {
+                                // Throw exception when expected values don't match
+                                throw new OperationApplicationException("Found value " + cursorValue
+                                        + " when expected " + expectedValue + " for column "
+                                        + projection[i]);
+                            }
                         }
                     }
                 }
@@ -395,12 +399,19 @@
 
         /** Create a ContentProviderOperation from this {@link Builder}. */
         public ContentProviderOperation build() {
-            if (mType == TYPE_UPDATE || mType == TYPE_ASSERT) {
+            if (mType == TYPE_UPDATE) {
                 if ((mValues == null || mValues.size() == 0)
                         && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) {
                     throw new IllegalArgumentException("Empty values");
                 }
             }
+            if (mType == TYPE_ASSERT) {
+                if ((mValues == null || mValues.size() == 0)
+                        && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)
+                        && (mExpectedCount == null)) {
+                    throw new IllegalArgumentException("Empty values");
+                }
+            }
             return new ContentProviderOperation(this);
         }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 88a4d02f..307899a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -527,12 +527,22 @@
         }
     }
 
-    class OpenResourceIdResult {
-        Resources r;
-        int id;
+    /**
+     * A resource identified by the {@link Resources} that contains it, and a resource id.
+     *
+     * @hide
+     */
+    public class OpenResourceIdResult {
+        public Resources r;
+        public int id;
     }
-    
-    OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
+
+    /**
+     * Resolves an android.resource URI to a {@link Resources} and a resource id.
+     *
+     * @hide
+     */
+    public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
         String authority = uri.getAuthority();
         Resources r;
         if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c053ace..fc977c8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -529,6 +529,8 @@
  *     <li> {@link #CATEGORY_HOME}
  *     <li> {@link #CATEGORY_PREFERENCE}
  *     <li> {@link #CATEGORY_TEST}
+ *     <li> {@link #CATEGORY_CAR_DOCK}
+ *     <li> {@link #CATEGORY_DESK_DOCK}
  * </ul>
  *
  * <h3>Standard Extra Data</h3>
@@ -1861,12 +1863,29 @@
      */
     public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
             "android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
+    /**
+     * An activity to run when device is inserted into a car dock.
+    * Used with {@link #ACTION_MAIN} to launch an activity.
+     * To monitor dock state, use {@link #ACTION_DOCK_EVENT} instead.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
+    /**
+     * An activity to run when device is inserted into a car dock.
+     * Used with {@link #ACTION_MAIN} to launch an activity.
+     * To monitor dock state, use {@link #ACTION_DOCK_EVENT} instead.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_DESK_DOCK = "android.intent.category.DESK_DOCK";
 
     /**
      * Broadcast Action:  The phone was docked or undocked.  Includes the extra
      * field {@link #EXTRA_DOCK_STATE}, containing the current dock state.
-     * @hide
+     * This is intended for monitoring the current dock state.
+     * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK}
+     * or {@link #CATEGORY_DESK_DOCK} instead.
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
 
     // ---------------------------------------------------------------------
@@ -2005,28 +2024,24 @@
      * {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED},
      * {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or
      * {@link android.content.Intent#EXTRA_DOCK_STATE_CAR}.
-     * @hide
      */
     public static final String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
 
     /**
      * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
      * to represent that the phone is not in any dock.
-     * @hide
      */
     public static final int EXTRA_DOCK_STATE_UNDOCKED = 0;
 
     /**
      * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
      * to represent that the phone is in a desk dock.
-     * @hide
      */
     public static final int EXTRA_DOCK_STATE_DESK = 1;
 
     /**
      * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
      * to represent that the phone is in a car dock.
-     * @hide
      */
     public static final int EXTRA_DOCK_STATE_CAR = 2;
 
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 27783ef..1ad13c5 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -217,7 +217,9 @@
     public static final int CONFIG_KEYBOARD = 0x0010;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
-     * can itself handle changes to the keyboard being hidden/exposed. 
+     * can itself handle changes to the keyboard or navigation being hidden/exposed.
+     * Note that inspite of the name, this applies to the changes to any
+     * hidden states: keyboard or navigation.
      * Set from the {@link android.R.attr#configChanges} attribute.
      */
     public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index cbf8410..1fe34b5 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -138,6 +138,18 @@
      */
     public int navigation;
     
+    public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
+    public static final int NAVIGATIONHIDDEN_NO = 1;
+    public static final int NAVIGATIONHIDDEN_YES = 2;
+    
+    /**
+     * A flag indicating whether any 5-way or DPAD navigation available.
+     * This will be set on a device with a mechanism to hide the navigation
+     * controls from the user, when that mechanism is closed.  One of:
+     * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
+     */
+    public int navigationHidden;
+    
     public static final int ORIENTATION_UNDEFINED = 0;
     public static final int ORIENTATION_PORTRAIT = 1;
     public static final int ORIENTATION_LANDSCAPE = 2;
@@ -174,6 +186,7 @@
         keyboardHidden = o.keyboardHidden;
         hardKeyboardHidden = o.hardKeyboardHidden;
         navigation = o.navigation;
+        navigationHidden = o.navigationHidden;
         orientation = o.orientation;
         screenLayout = o.screenLayout;
     }
@@ -198,6 +211,8 @@
         sb.append(hardKeyboardHidden);
         sb.append(" nav=");
         sb.append(navigation);
+        sb.append("/");
+        sb.append(navigationHidden);
         sb.append(" orien=");
         sb.append(orientation);
         sb.append(" layout=");
@@ -219,6 +234,7 @@
         keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
         navigation = NAVIGATION_UNDEFINED;
+        navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
     }
@@ -286,6 +302,11 @@
             changed |= ActivityInfo.CONFIG_NAVIGATION;
             navigation = delta.navigation;
         }
+        if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+                && navigationHidden != delta.navigationHidden) {
+            changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+            navigationHidden = delta.navigationHidden;
+        }
         if (delta.orientation != ORIENTATION_UNDEFINED
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -360,6 +381,10 @@
                 && navigation != delta.navigation) {
             changed |= ActivityInfo.CONFIG_NAVIGATION;
         }
+        if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+                && navigationHidden != delta.navigationHidden) {
+            changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+        }
         if (delta.orientation != ORIENTATION_UNDEFINED
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -416,6 +441,7 @@
         dest.writeInt(keyboardHidden);
         dest.writeInt(hardKeyboardHidden);
         dest.writeInt(navigation);
+        dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
     }
@@ -448,6 +474,7 @@
         keyboardHidden = source.readInt();
         hardKeyboardHidden = source.readInt();
         navigation = source.readInt();
+        navigationHidden = source.readInt();
         orientation = source.readInt();
         screenLayout = source.readInt();
     }
@@ -478,6 +505,8 @@
         if (n != 0) return n;
         n = this.navigation - that.navigation;
         if (n != 0) return n;
+        n = this.navigationHidden - that.navigationHidden;
+        if (n != 0) return n;
         n = this.orientation - that.orientation;
         if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
@@ -503,6 +532,7 @@
         return ((int)this.fontScale) + this.mcc + this.mnc
                 + this.locale.hashCode() + this.touchscreen
                 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
-                + this.navigation + this.orientation + this.screenLayout;
+                + this.navigation + this.navigationHidden
+                + this.orientation + this.screenLayout;
     }
 }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 9991600..13effe0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -38,12 +38,12 @@
  * <p>There is no default constructor for this class. Use {@link #open()} to
  * get a Camera object.</p>
  *
- * <p>In order to use the device camera, you must declare the 
- * {@link android.Manifest.permission#CAMERA} permission in your Android 
+ * <p>In order to use the device camera, you must declare the
+ * {@link android.Manifest.permission#CAMERA} permission in your Android
  * Manifest. Also be sure to include the
  * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
- * manifest element in order to declare camera features used by your application. 
- * For example, if you use the camera and auto-focus feature, your Manifest 
+ * manifest element in order to declare camera features used by your application.
+ * For example, if you use the camera and auto-focus feature, your Manifest
  * should include the following:</p>
  * <pre> &lt;uses-permission android:name="android.permission.CAMERA" />
  * &lt;uses-feature android:name="android.hardware.camera" />
@@ -52,7 +52,7 @@
  * <p class="caution"><strong>Caution:</strong> Different Android-powered devices
  * may have different hardware specifications, such as megapixel ratings and
  * auto-focus capabilities. In order for your application to be compatible with
- * more devices, you should not make assumptions about the device camera 
+ * more devices, you should not make assumptions about the device camera
  * specifications.</p>
  */
 public class Camera {
@@ -197,7 +197,7 @@
          * The callback that delivers the preview frames.
          *
          * @param data The contents of the preview frame in the format defined
-         *  by {@link android.graphics.PixelFormat}, which can be queried 
+         *  by {@link android.graphics.PixelFormat}, which can be queried
          *  with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
          *  If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
          *             is never called, the default will be the YCbCr_420_SP
@@ -340,11 +340,11 @@
 
     /**
      * Handles the callback for the camera auto focus.
-     * <p>Devices that do not support auto-focus will receive a "fake" 
-     * callback to this interface. If your application needs auto-focus and 
+     * <p>Devices that do not support auto-focus will receive a "fake"
+     * callback to this interface. If your application needs auto-focus and
      * should not be installed on devices <em>without</em> auto-focus, you must
      * declare that your app uses the
-     * {@code android.hardware.camera.autofocus} feature, in the 
+     * {@code android.hardware.camera.autofocus} feature, in the
      * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
      * manifest element.</p>
      */
@@ -368,11 +368,11 @@
      * AutoFocusCallback#onAutoFocus(boolean, Camera)} callback will be called
      * immediately.
      * <p>If your application should not be installed
-     * on devices without auto-focus, you must declare that your application 
-     * uses auto-focus with the 
+     * on devices without auto-focus, you must declare that your application
+     * uses auto-focus with the
      * <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature></a>
      * manifest element.</p>
-     * 
+     *
      * @param cb the callback to run
      */
     public final void autoFocus(AutoFocusCallback cb)
@@ -387,7 +387,6 @@
      * this function will cancel it. Whether the auto-focus is in progress
      * or not, this function will return the focus position to the default.
      * If the camera does not support auto-focus, this is a no-op.
-     * @hide
      */
     public final void cancelAutoFocus()
     {
@@ -917,11 +916,11 @@
         }
 
         /**
-         * Sets the image format for preview pictures. 
+         * Sets the image format for preview pictures.
          * <p>If this is never called, the default format will be
          * {@link android.graphics.PixelFormat#YCbCr_420_SP}, which
          * uses the NV21 encoding format.</p>
-         * 
+         *
          * @param pixel_format the desired preview picture format, defined
          *   by one of the {@link android.graphics.PixelFormat} constants.
          *   (E.g., <var>PixelFormat.YCbCr_420_SP</var> (default),
@@ -942,8 +941,8 @@
         /**
          * Returns the image format for preview pictures got from
          * {@link PreviewCallback}.
-         * 
-         * @return the {@link android.graphics.PixelFormat} int representing 
+         *
+         * @return the {@link android.graphics.PixelFormat} int representing
          *         the preview picture format.
          */
         public int getPreviewFormat() {
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 666efae..cc48aeb 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -31,6 +31,9 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.TextView;
 
 /**
@@ -297,10 +300,32 @@
         if (state != null) {
             dialog.onRestoreInstanceState(state);
         }
+        if (needInputMethod()) {
+            requestInputMethod(dialog);
+        }
         dialog.setOnDismissListener(this);
         dialog.show();
     }
-    
+
+    /**
+     * Returns whether the preference needs to display a soft input method when the dialog
+     * is displayed. Default is false. Subclasses should override this method if they need
+     * the soft input method brought up automatically.
+     * @hide
+     */
+    protected boolean needInputMethod() {
+        return false;
+    }
+
+    /**
+     * Sets the required flags on the dialog window to enable input method window to show up.
+     */
+    private void requestInputMethod(Dialog dialog) {
+        Window window = dialog.getWindow();
+        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE |
+                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+    }
+
     /**
      * Creates the content view for the dialog (if a custom content view is
      * required). By default, it inflates the dialog layout resource if it is
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index a12704f..84ee950 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -169,6 +169,13 @@
         return mEditText;
     }
 
+    /** @hide */
+    @Override
+    protected boolean needInputMethod() {
+        // We want the input method to show, if possible, when dialog is displayed
+        return true;
+    }
+
     @Override
     protected Parcelable onSaveInstanceState() {
         final Parcelable superState = super.onSaveInstanceState();
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b0ac7f4..6eaf9dd 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1039,6 +1039,7 @@
             public static final int TYPE_WORK_MOBILE = 17;
             public static final int TYPE_WORK_PAGER = 18;
             public static final int TYPE_ASSISTANT = 19;
+            public static final int TYPE_MMS = 20;
 
             /**
              * The phone number as the user entered it.
@@ -1529,7 +1530,7 @@
          * called on a raw contact, it is marked for deletion and removed from its
          * aggregate contact. The sync adaptor deletes the raw contact on the server and
          * then calls ContactResolver.delete once more, this time setting the the
-         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 
+         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
          * the data removal.
          * <P>Type: INTEGER</P>
          */
@@ -1686,6 +1687,13 @@
         public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
 
         /**
+         * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
+         * {@link Groups#SHOULD_SYNC} under this account have been marked as
+         * unsynced.
+         */
+        public static final String ANY_UNSYNCED = "any_unsynced";
+
+        /**
          * Read-only count of {@link Contacts} from a specific source that have
          * no {@link CommonDataKinds.GroupMembership} entries.
          * <p>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0bbd1fc..6d03095 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2758,11 +2758,19 @@
 
         /**
          * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be
-         * an integer where non-zero means true. Defaults to 1.
+         * an integer where non-zero means true. Defaults to 1. This flag controls Donut devices.
          */
         public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op";
 
         /**
+         * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be
+         * an integer where non-zero means true. Defaults to 1. This flag controls Eclair and
+         * future devices.
+         */
+        public static final String GMAIL_DISCARD_ERROR_UPHILL_OP_NEW =
+            "gmail_discard_error_uphill_op_new";
+
+        /**
          * Controls how many attempts Gmail will try to upload an uphill operations before it
          * abandons the operation. Defaults to 20.
          */
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 9c687e2..be8c777 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -27,6 +27,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.IBluetoothA2dp;
+import android.bluetooth.ParcelUuid;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -42,7 +43,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
-import java.util.UUID;
 
 public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
     private static final String TAG = "BluetoothA2dpService";
@@ -188,15 +188,9 @@
     }
 
     private boolean isSinkDevice(BluetoothDevice device) {
-        String uuids[] = mBluetoothService.getRemoteUuids(device.getAddress());
-        UUID uuid;
-        if (uuids != null) {
-            for (String deviceUuid: uuids) {
-                uuid = UUID.fromString(deviceUuid);
-                if (BluetoothUuid.isAudioSink(uuid)) {
-                    return true;
-                }
-            }
+        ParcelUuid[] uuids = mBluetoothService.getRemoteUuids(device.getAddress());
+        if (uuids != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
+            return true;
         }
         return false;
     }
@@ -229,18 +223,14 @@
             for (String path: paths) {
                 String address = mBluetoothService.getAddressFromObjectPath(path);
                 BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                String []uuids = mBluetoothService.getRemoteUuids(address);
-                if (uuids != null)
-                    for (String uuid: uuids) {
-                        UUID remoteUuid = UUID.fromString(uuid);
-                        if (BluetoothUuid.isAudioSink(remoteUuid) ||
-                            BluetoothUuid.isAudioSource(remoteUuid) ||
-                            BluetoothUuid.isAdvAudioDist(remoteUuid)) {
-                            addAudioSink(device);
-                            break;
-                        }
+                ParcelUuid[] remoteUuids = mBluetoothService.getRemoteUuids(address);
+                if (remoteUuids != null)
+                    if (BluetoothUuid.containsAnyUuid(remoteUuids,
+                            new ParcelUuid[] {BluetoothUuid.AudioSink,
+                                                BluetoothUuid.AdvAudioDist})) {
+                        addAudioSink(device);
                     }
-            }
+                }
         }
         mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
     }
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 1ed5c49..ba53307 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
+import android.bluetooth.ParcelUuid;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
@@ -28,7 +29,6 @@
 import android.util.Log;
 
 import java.util.HashMap;
-import java.util.UUID;
 
 /**
  * TODO: Move this to
@@ -501,7 +501,7 @@
         }
 
         boolean authorized = false;
-        UUID uuid = UUID.fromString(deviceUuid);
+        ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
         // Bluez sends the UUID of the local service being accessed, _not_ the
         // remote service
         if (mBluetoothService.isEnabled() &&
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index de0cad7..c0e4f34 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -24,11 +24,12 @@
 
 package android.server;
 
-import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.IBluetooth;
+import android.bluetooth.ParcelUuid;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -51,7 +52,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 public class BluetoothService extends IBluetooth.Stub {
@@ -967,22 +967,26 @@
 
 
     /**
-     * Gets the remote features encoded as bit mask.
+     * Gets the UUIDs supported by the remote device
      *
-     * Note: This method may be obsoleted soon.
-     *
-     * @return String array of 128bit UUIDs
+     * @return array of 128bit ParcelUuids
      */
-    public synchronized String[] getRemoteUuids(String address) {
+    public synchronized ParcelUuid[] getRemoteUuids(String address) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             return null;
         }
         String value = getRemoteDeviceProperty(address, "UUIDs");
-        String[] uuids = null;
+        if (value == null) return null;
+
+        String[] uuidStrings = null;
         // The UUIDs are stored as a "," separated string.
-        if (value != null)
-             uuids = value.split(",");
+        uuidStrings = value.split(",");
+        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
+
+        for (int i = 0; i < uuidStrings.length; i++) {
+            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
+        }
         return uuids;
     }
 
@@ -990,16 +994,17 @@
      * Gets the rfcomm channel associated with the UUID.
      *
      * @param address Address of the remote device
-     * @param uuid UUID of the service attribute
+     * @param uuid ParcelUuid of the service attribute
      *
      * @return rfcomm channel associated with the service attribute
      */
-    public int getRemoteServiceChannel(String address, String uuid) {
+    public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             return BluetoothDevice.ERROR;
         }
-        return getDeviceServiceChannelNative(getObjectPathFromAddress(address), uuid, 0x0004);
+        return getDeviceServiceChannelNative(getObjectPathFromAddress(address), uuid.toString(),
+                0x0004);
     }
 
     public synchronized boolean setPin(String address, byte[] pin) {
@@ -1148,11 +1153,11 @@
                        mBondState.getAttempt(address),
                        getRemoteName(address));
             if (bondState == BluetoothDevice.BOND_BONDED) {
-                String[] uuids = getRemoteUuids(address);
+                ParcelUuid[] uuids = getRemoteUuids(address);
                 if (uuids == null) {
                     pw.printf("\tuuids = null\n");
                 } else {
-                    for (String uuid : uuids) {
+                    for (ParcelUuid uuid : uuids) {
                         pw.printf("\t" + uuid + "\n");
                     }
                 }
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index d50684a..14b8308 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -128,6 +128,15 @@
      */
     public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
     
+    /**
+     * Flag for {@link #TYPE_CLASS_TEXT}: the input method does not need to
+     * display any dictionary-based candidates. This is useful for text views that
+     * do not contain words from the language and do not benefit from any
+     * dictionary-based completions or corrections. It overrides the
+     * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set.
+     */
+    public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;
+
     // ----------------------------------------------------------------------
     
     /**
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 38881d3..f736f85 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -431,6 +431,7 @@
         PICKER_SETS.put('z', "\u017A\u017C\u017E");
         PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
                              "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\");
+        PICKER_SETS.put('/', "\\");
 
         // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml
 
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 94acd3f..e5985c1 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -458,11 +458,12 @@
     public final View createView(String name, String prefix, AttributeSet attrs)
             throws ClassNotFoundException, InflateException {
         Constructor constructor = sConstructorMap.get(name);
+        Class clazz = null;
 
         try {
             if (constructor == null) {
                 // Class not found in the cache, see if it's real, and try to add it
-                Class clazz = mContext.getClassLoader().loadClass(
+                clazz = mContext.getClassLoader().loadClass(
                         prefix != null ? (prefix + name) : name);
                 
                 if (mFilter != null && clazz != null) {
@@ -480,7 +481,7 @@
                     Boolean allowedState = mFilterMap.get(name);
                     if (allowedState == null) {
                         // New class -- remember whether it is allowed
-                        Class clazz = mContext.getClassLoader().loadClass(
+                        clazz = mContext.getClassLoader().loadClass(
                                 prefix != null ? (prefix + name) : name);
                         
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
@@ -511,7 +512,7 @@
         } catch (Exception e) {
             InflateException ie = new InflateException(attrs.getPositionDescription()
                     + ": Error inflating class "
-                    + (constructor == null ? "<unknown>" : constructor.getClass().getName()));
+                    + (clazz == null ? "<unknown>" : clazz.getName()));
             ie.initCause(e);
             throw ie;
         }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8c12656..f67c4aa 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -500,6 +500,12 @@
          */
         public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
         
+        /** Window flag: when set as a window is being added or made
+         * visible, once the window has been shown then the system will
+         * poke the power manager's user activity (as if the user had woken
+         * up the device) to turn the screen on. */
+        public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
+        
         /** Window flag: special flag to limit the size of the window to be
          * original size ([320x480] x density). Used to create window for applications
          * running under compatibility mode.
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 95b3a12..39a2470 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import com.android.internal.widget.EditableInputConnection;
+
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -38,6 +40,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -346,6 +349,16 @@
 
     @Override
     protected void onSelectionChanged(int selStart, int selEnd) {
+        // This code is copied from TextView.onDraw().  That code does not get
+        // executed, however, because the WebTextView does not draw, allowing
+        // webkit's drawing to show through.
+        InputMethodManager imm = InputMethodManager.peekInstance();
+        if (imm != null && imm.isActive(this)) {
+            Spannable sp = (Spannable) getText();
+            int candStart = EditableInputConnection.getComposingSpanStart(sp);
+            int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
+            imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
+        }
         if (!mFromWebKit && mWebView != null) {
             if (DebugFlags.WEB_TEXT_VIEW) {
                 Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart
@@ -430,18 +443,26 @@
             mGotTouchDown = true;
             break;
         case MotionEvent.ACTION_MOVE:
+            int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
             Spannable buffer = getText();
             int initialScrollX = Touch.getInitialScrollX(this, buffer);
             int initialScrollY = Touch.getInitialScrollY(this, buffer);
             super.onTouchEvent(event);
-            if (mScrollX != initialScrollX
-                    || mScrollY != initialScrollY) {
+            if (Math.abs(mScrollX - initialScrollX) > slop
+                    || Math.abs(mScrollY - initialScrollY) > slop) {
                 if (mWebView != null) {
                     mWebView.scrollFocusedTextInput(mScrollX, mScrollY);
                 }
                 mScrolled = true;
                 return true;
             }
+            if (Math.abs((int) event.getX() - mDragStartX) < slop
+                    && Math.abs((int) event.getY() - mDragStartY) < slop) {
+                // If the user has not scrolled further than slop, we should not
+                // send the drag.  Instead, do nothing, and when the user lifts
+                // their finger, we will change the selection.
+                return true;
+            }
             if (mWebView != null) {
                 // Only want to set the initial state once.
                 if (!mDragSent) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 081f67a..abbbc00 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -420,6 +420,7 @@
     private static final int STD_SPEED = 480;  // pixels per second
     // time for the longest scroll animation
     private static final int MAX_DURATION = 750;   // milliseconds
+    private static final int SLIDE_TITLE_DURATION = 300;   // milliseconds
     private Scroller mScroller;
 
     private boolean mWrapContent;
@@ -2416,10 +2417,18 @@
         if ((dx | dy) == 0) {
             return false;
         }
-
-        if (true && animate) {
+        // mobile sites prefer to scroll to (0, 1), thus the + 1 below
+        boolean slideTitle = getVisibleTitleHeight() > 0
+            && y <= getTitleHeight() + 1;
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "pinScrollTo slideTitle=" + slideTitle
+                    + " getVisibleTitleHeight()=" + getVisibleTitleHeight()
+                    + " animationDuration=" + animationDuration + " y=" + y);
+        }
+        if (slideTitle || animate) {
             //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
-
+            if (slideTitle && animationDuration < SLIDE_TITLE_DURATION)
+                animationDuration = SLIDE_TITLE_DURATION;
             mScroller.startScroll(mScrollX, mScrollY, dx, dy,
                     animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
             invalidate();
@@ -4791,8 +4800,11 @@
                             mMaxZoomScale = restoreState.mMaxScale;
                         }
                         setNewZoomScale(mLastScale, false);
-                        setContentScrollTo(restoreState.mScrollX,
-                                restoreState.mScrollY);
+                        if (getVisibleTitleHeight() == 0
+                                || restoreState.mScrollY != 0) {
+                            setContentScrollTo(restoreState.mScrollX,
+                                    restoreState.mScrollY);
+                        }
                         if (useWideViewport
                                 && settings.getLoadWithOverviewMode()) {
                             if (restoreState.mViewScale == 0
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index fe01866..4ec597c 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -42,6 +42,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.CheckBox;
+import android.widget.FasttrackBadgeWidget;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -64,15 +65,13 @@
     private TextView mDisplayNameView;
     private TextView mPhoneticNameView;
     private CheckBox mStarredView;
-    private ImageView mPhotoView;
+    private FasttrackBadgeWidget mPhotoView;
     private ImageView mPresenceView;
     private TextView mStatusView;
     private int mNoPhotoResource;
     private QueryHandler mQueryHandler;
 
-    protected long mContactId;
     protected Uri mContactUri;
-    protected Uri mStatusUri;
 
     protected String[] mExcludeMimes = null;
 
@@ -94,6 +93,8 @@
         Contacts.STARRED,
         Contacts.PHOTO_ID,
         Contacts.PRESENCE_STATUS,
+        Contacts._ID,
+        Contacts.LOOKUP_KEY,
     };
     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.
@@ -101,6 +102,8 @@
     protected static final int HEADER_STARRED_COLUMN_INDEX = 1;
     protected static final int HEADER_PHOTO_ID_COLUMN_INDEX = 2;
     protected static final int HEADER_PRESENCE_STATUS_COLUMN_INDEX = 3;
+    protected static final int HEADER_CONTACT_ID_COLUMN_INDEX = 4;
+    protected static final int HEADER_LOOKUP_KEY_COLUMN_INDEX = 5;
 
     //Projection used for finding the most recent social status.
     protected static final String[] SOCIAL_PROJECTION = new String[] {
@@ -113,18 +116,29 @@
     //Projection used for looking up contact id from phone number
     protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
         PhoneLookup._ID,
+        PhoneLookup.LOOKUP_KEY,
     };
     protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+    protected static final int PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
 
     //Projection used for looking up contact id from email address
     protected static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
         RawContacts.CONTACT_ID,
+        Contacts.LOOKUP_KEY,
     };
     protected static final int EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+    protected static final int EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
 
+    protected static final String[] CONTACT_LOOKUP_PROJECTION = new String[] {
+        Contacts._ID,
+    };
+    protected static final int CONTACT_LOOKUP_ID_COLUMN_INDEX = 0;
 
     private static final int TOKEN_CONTACT_INFO = 0;
     private static final int TOKEN_SOCIAL = 1;
+    private static final int TOKEN_PHONE_LOOKUP = 2;
+    private static final int TOKEN_EMAIL_LOOKUP = 3;
+    private static final int TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY = 4;
 
     public ContactHeaderWidget(Context context) {
         this(context, null);
@@ -151,8 +165,7 @@
         mStarredView = (CheckBox)findViewById(R.id.star);
         mStarredView.setOnClickListener(this);
 
-        mPhotoView = (ImageView)findViewById(R.id.photo);
-        mPhotoView.setOnClickListener(this);
+        mPhotoView = (FasttrackBadgeWidget) findViewById(R.id.photo);
         mPhotoView.setOnLongClickListener(this);
 
         mPresenceView = (ImageView) findViewById(R.id.presence);
@@ -217,12 +230,46 @@
         @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();
+                switch (token) {
+                    case TOKEN_CONTACT_INFO: {
+                        bindContactInfo(cursor);
+                        invalidate();
+                        break;
+                    }
+                    case TOKEN_SOCIAL: {
+                        bindSocial(cursor);
+                        invalidate();
+                        break;
+                    }
+                    case TOKEN_PHONE_LOOKUP: {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            long contactId = cursor.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+                            String lookupKey = cursor.getString(
+                                    PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
+                            bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey));
+                        } else {
+                            setDisplayName((String) cookie, null);
+                        }
+                        break;
+                    }
+                    case TOKEN_EMAIL_LOOKUP: {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            long contactId = cursor.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+                            String lookupKey = cursor.getString(
+                                    EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
+                            bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey));
+                        } else {
+                            setDisplayName((String) cookie, null);
+                        }
+                        break;
+                    }
+                    case TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY: {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            long contactId = cursor.getLong(CONTACT_LOOKUP_ID_COLUMN_INDEX);
+                            startSocialQuery(ContentUris.withAppendedId(
+                                    Activities.CONTENT_CONTACT_STATUS_URI, contactId));
+                        }
+                    }
                 }
             } finally {
                 if (cursor != null) {
@@ -300,33 +347,31 @@
      * Convenience method for binding all available data from an existing
      * contact.
      *
-     * @param contactId the contact id of the contact whose info should be displayed.
+     * @param conatctUri a {Contacts.CONTENT_LOOKUP_URI} style URI.
      */
-    public void bindFromContactId(long contactId) {
-        mContactId = contactId;
-        mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId);
+    public void bindFromContactLookupUri(Uri contactLookupUri) {
+        mContactUri = contactLookupUri;
 
-        bindContactUri(mContactUri);
-        bindSocialUri(ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mContactId));
+        // Query for the contactId so we can do the social query.
+        mQueryHandler.startQuery(TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY, null, contactLookupUri,
+                CONTACT_LOOKUP_PROJECTION, null, null, null);
+
+        startContactQuery(contactLookupUri);
     }
 
     /**
-     * Convenience method for binding {@link Contacts} header details from a
-     * {@link Contacts#CONTENT_URI} reference.
+     * Convenience method for binding all available data from an existing
+     * contact.
+     *
+     * @param conatctUri a {Contacts.CONTENT_URI} style URI.
      */
-    public void bindContactUri(Uri contactUri) {
-        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION,
-                null, null, null);
-    }
+    public void bindFromContactUri(Uri contactUri) {
+        mContactUri = contactUri;
+        long contactId = ContentUris.parseId(contactUri);
 
-    /**
-     * Convenience method for binding {@link Activities} header details from a
-     * {@link Activities#CONTENT_CONTACT_STATUS_URI}.
-     */
-    public void bindSocialUri(Uri contactSocial) {
-        mStatusUri = contactSocial;
-        mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null,
-                null);
+        startContactQuery(contactUri);
+        startSocialQuery(ContentUris.withAppendedId(
+                Activities.CONTENT_CONTACT_STATUS_URI, contactId));
     }
 
     /**
@@ -338,21 +383,9 @@
      * address, one of them will be chosen to bind to.
      */
     public void bindFromEmail(String emailAddress) {
-        Cursor c = null;
-        try {
-            c = mContentResolver.query(Uri.withAppendedPath(Email.CONTENT_FILTER_EMAIL_URI, Uri
-                    .encode(emailAddress)), EMAIL_LOOKUP_PROJECTION, null, null, null);
-            if (c != null && c.moveToFirst()) {
-                long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
-                bindFromContactId(contactId);
-            } else {
-                setDisplayName(emailAddress, null);
-            }
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
+        mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, emailAddress,
+                Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)),
+                EMAIL_LOOKUP_PROJECTION, null, null, null);
     }
 
     /**
@@ -364,22 +397,19 @@
      * 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, Uri.encode(number)),
-                    PHONE_LOOKUP_PROJECTION, null, null, null);
-            if (c != null && c.moveToFirst()) {
-                long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
-                bindFromContactId(contactId);
-            } else {
-                setDisplayName(number, null);
-            }
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
+        mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, number,
+                Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
+                PHONE_LOOKUP_PROJECTION, null, null, null);
+    }
+
+    private void startSocialQuery(Uri contactSocial) {
+        mQueryHandler.startQuery(TOKEN_SOCIAL, null, contactSocial, SOCIAL_PROJECTION, null, null,
+                null);
+    }
+
+    private void startContactQuery(Uri contactUri) {
+        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION,
+                null, null, null);
     }
 
     /**
@@ -390,6 +420,8 @@
 
         // TODO: Bring back phonetic name
         final String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
+        final long contactId = c.getLong(HEADER_CONTACT_ID_COLUMN_INDEX);
+        final String lookupKey = c.getString(HEADER_LOOKUP_KEY_COLUMN_INDEX);
         final String phoneticName = null;
         this.setDisplayName(displayName, null);
 
@@ -402,6 +434,7 @@
             photoBitmap = loadPlaceholderPhoto(null);
         }
         mPhotoView.setImageBitmap(photoBitmap);
+        mPhotoView.assignContactUri(Contacts.getLookupUri(contactId, lookupKey));
 
         //Set the presence status
         int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX);
@@ -423,27 +456,11 @@
             return;
         }
 
-        switch (view.getId()) {
-            case R.id.star: {
-                // Toggle "starred" state
-                final ContentValues values = new ContentValues(1);
-                values.put(Contacts.STARRED, mStarredView.isChecked());
-                mContentResolver.update(mContactUri, values, null, null);
-                break;
-            }
-            case R.id.photo: {
-                // Photo launches contact detail action
-                final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, mContactUri);
-                final Rect target = getTargetRect(view);
-                intent.putExtra(Intents.EXTRA_TARGET_RECT, target);
-                intent.putExtra(Intents.EXTRA_MODE, Intents.MODE_SMALL);
-                if (mExcludeMimes != null) {
-                    // Exclude specific MIME-types when requested
-                    intent.putExtra(Intents.EXTRA_EXCLUDE_MIMES, mExcludeMimes);
-                }
-                mContext.startActivity(intent);
-                break;
-            }
+        if (view.getId() == R.id.star) {
+            // Toggle "starred" state
+            final ContentValues values = new ContentValues(1);
+            values.put(Contacts.STARRED, mStarredView.isChecked());
+            mContentResolver.update(mContactUri, values, null, null);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
index 7b940c9..aff92b8 100644
--- a/core/java/com/android/internal/widget/RotarySelector.java
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -19,8 +19,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.Vibrator;
 import android.util.AttributeSet;
@@ -28,7 +26,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
-
+import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
 import com.android.internal.R;
 
 
@@ -69,7 +67,7 @@
     private boolean mAnimating = false;
     private long mAnimationEndTime;
     private int mAnimatingDelta;
-    AccelerateInterpolator mInterpolator;
+    private AccelerateInterpolator mInterpolator;
 
     /**
      * True after triggering an action if the user of {@link OnDialTriggerListener} wants to
@@ -96,12 +94,6 @@
     private static final long VIBRATE_SHORT = 60;  // msec
     private static final long VIBRATE_LONG = 100;  // msec
 
-    // Various tweakable layout or behavior parameters:
-
-    // How close to the edge of the screen, we let the handle get before
-    // triggering an action:
-    private static final int EDGE_THRESHOLD_DIP = 70;
-
     /**
      * The drawable for the arrows need to be scrunched this many dips towards the rotary bg below
      * it.
@@ -122,6 +114,11 @@
 
     private static final boolean DRAW_CENTER_DIMPLE = false;
 
+    public RotarySelector(Context context) {
+        this(context, null);
+    }
+
+
     /**
      * Constructor used when this widget is created from a layout file.
      */
@@ -132,8 +129,6 @@
         Resources r = getResources();
         mDensity = r.getDisplayMetrics().density;
         if (DBG) log("- Density: " + mDensity);
-        // Density is 1.0 on HVGA (like Dream), and 1.5 on WVGA.
-        // Usage: raw_pixel_value = (int) (dpi_value * mDensity + 0.5f)
 
         // Assets (all are BitmapDrawables).
         mBackground = r.getDrawable(R.drawable.jog_dial_bg_cropped);
@@ -143,6 +138,15 @@
         mArrowLongRight = r.getDrawable(R.drawable.jog_dial_arrow_long_right_red);
         mArrowShortLeftAndRight = r.getDrawable(R.drawable.jog_dial_arrow_short_left_and_right);
 
+        // Arrows:
+        // All arrow assets are the same size (they're the full width of
+        // the screen) regardless of which arrows are actually visible.
+        int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth();
+        int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
+        mArrowShortLeftAndRight.setBounds(0, 0, arrowW, arrowH);
+        mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
+        mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
+
         mInterpolator = new AccelerateInterpolator();
     }
 
@@ -237,7 +241,7 @@
 
         // update animating state before we draw anything
         if (mAnimating && !mFrozen) {
-            long millisLeft = mAnimationEndTime - System.currentTimeMillis();
+            long millisLeft = mAnimationEndTime - currentAnimationTimeMillis();
             if (DBG) log("millisleft for animating: " + millisLeft);
             if (millisLeft <= 0) {
                 reset();
@@ -259,11 +263,6 @@
         if (DBG) log("  Background BOUNDS: " + mBackground.getBounds());
         mBackground.draw(canvas);
 
-        // Arrows:
-        // All arrow assets are the same size (they're the full width of
-        // the screen) regardless of which arrows are actually visible.
-        int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth();
-        int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
 
         // Draw the correct arrow(s) depending on the current state:
         Drawable currentArrow;
@@ -280,7 +279,6 @@
             default:
                 throw new IllegalStateException("invalid mGrabbedState: " + mGrabbedState);
         }
-        currentArrow.setBounds(0, 0, arrowW, arrowH);
         currentArrow.draw(canvas);
 
         // debug: draw circle that should match the outer arc (good sanity check)
@@ -382,63 +380,70 @@
         final int eventX = (int) event.getX();
         final int hitWindow = mDimple.getIntrinsicWidth();
 
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            if (DBG) log("touch-down");
-            mTriggered = false;
-            if (mGrabbedState != RotarySelector.NOTHING_GRABBED) {
+        final int action = event.getAction();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                if (DBG) log("touch-down");
+                mTriggered = false;
+                if (mGrabbedState != NOTHING_GRABBED) {
+                    reset();
+                    invalidate();
+                }
+                if (eventX < mLeftHandleX + hitWindow) {
+                    mTouchDragOffset = eventX - mLeftHandleX;
+                    mGrabbedState = LEFT_HANDLE_GRABBED;
+                    invalidate();
+                    vibrate(VIBRATE_SHORT);
+                } else if (eventX > mRightHandleX - hitWindow) {
+                    mTouchDragOffset = eventX - mRightHandleX;
+                    mGrabbedState = RIGHT_HANDLE_GRABBED;
+                    invalidate();
+                    vibrate(VIBRATE_SHORT);
+                }
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (DBG) log("touch-move");
+                if (mGrabbedState == LEFT_HANDLE_GRABBED) {
+                    mTouchDragOffset = eventX - mLeftHandleX;
+                    invalidate();
+                    if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) {
+                        mTriggered = true;
+                        mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
+                    }
+                } else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
+                    mTouchDragOffset = eventX - mRightHandleX;
+                    invalidate();
+                    if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
+                        mTriggered = true;
+                        mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (DBG) log("touch-up");
+                // handle animating back to start if they didn't trigger
+                if (mGrabbedState == LEFT_HANDLE_GRABBED
+                        && Math.abs(eventX - mLeftHandleX) > 5) {
+                    mAnimating = true;
+                    mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS;
+                    mAnimatingDelta = eventX - mLeftHandleX;
+                } else if (mGrabbedState == RIGHT_HANDLE_GRABBED
+                        && Math.abs(eventX - mRightHandleX) > 5) {
+                    mAnimating = true;
+                    mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS;
+                    mAnimatingDelta = eventX - mRightHandleX;
+                }
+
+                mTouchDragOffset = 0;
+                mGrabbedState = NOTHING_GRABBED;
+                invalidate();
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                if (DBG) log("touch-cancel");
                 reset();
                 invalidate();
-            }
-            if (eventX < mLeftHandleX + hitWindow) {
-                mTouchDragOffset = eventX - mLeftHandleX;
-                mGrabbedState = RotarySelector.LEFT_HANDLE_GRABBED;
-                invalidate();
-                vibrate(VIBRATE_SHORT);
-            } else if (eventX > mRightHandleX - hitWindow) {
-                mTouchDragOffset = eventX - mRightHandleX;
-                mGrabbedState = RotarySelector.RIGHT_HANDLE_GRABBED;
-                invalidate();
-                vibrate(VIBRATE_SHORT);
-            }
-        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
-            if (DBG) log("touch-move");
-            if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED) {
-                mTouchDragOffset = eventX - mLeftHandleX;
-                invalidate();
-                if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) {
-                    mTriggered = true;
-                    mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
-                }
-            } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED) {
-                mTouchDragOffset = eventX - mRightHandleX;
-                invalidate();
-                if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
-                    mTriggered = true;
-                    mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
-                }
-            }
-        } else if ((event.getAction() == MotionEvent.ACTION_UP)) {
-            if (DBG) log("touch-up");
-            // handle animating back to start if they didn't trigger
-            if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED
-                    && Math.abs(eventX - mLeftHandleX) > 5) {
-                mAnimating = true;
-                mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
-                mAnimatingDelta = eventX - mLeftHandleX;
-            } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED
-                    && Math.abs(eventX - mRightHandleX) > 5) {
-                mAnimating = true;
-                mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
-                mAnimatingDelta = eventX - mRightHandleX;
-            }
-
-            mTouchDragOffset = 0;
-            mGrabbedState = RotarySelector.NOTHING_GRABBED;
-            invalidate();
-        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
-            if (DBG) log("touch-cancel");
-            reset();
-            invalidate();
+                break;
         }
         return true;
     }
@@ -446,7 +451,7 @@
     private void reset() {
         mAnimating = false;
         mTouchDragOffset = 0;
-        mGrabbedState = RotarySelector.NOTHING_GRABBED;
+        mGrabbedState = NOTHING_GRABBED;
         mTriggered = false;
     }
 
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index a185d8d..ba13519 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -133,23 +133,13 @@
     LOGV(__FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
-        DBusError err;
-        dbus_error_init(&err);
 
-        DBusMessage *reply =
-                dbus_func_args_timeout(env, nat->conn, -1, c_path,
-                               "org.bluez.AudioSink", "Connect",
-                                DBUS_TYPE_INVALID);
+        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+                                    c_path, "org.bluez.AudioSink", "Connect",
+                                    DBUS_TYPE_INVALID);
+
         env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply && dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-            return JNI_FALSE;
-        } else if (!reply) {
-            LOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return JNI_FALSE;
-        }
-        return JNI_TRUE;
+        return ret ? JNI_TRUE : JNI_FALSE;
     }
 #endif
     return JNI_FALSE;
@@ -161,23 +151,13 @@
     LOGV(__FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
-        DBusError err;
-        dbus_error_init(&err);
 
-        DBusMessage *reply =
-              dbus_func_args_timeout(env, nat->conn, -1, c_path,
-                                     "org.bluez.AudioSink", "Disconnect",
-                                     DBUS_TYPE_INVALID);
+        bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+                                    c_path, "org.bluez.AudioSink", "Disconnect",
+                                    DBUS_TYPE_INVALID);
+
         env->ReleaseStringUTFChars(path, c_path);
-
-        if (!reply && dbus_error_is_set(&err)) {
-            LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
-            return JNI_FALSE;
-        } else if (!reply) {
-            LOGE("DBus reply is NULL in function %s", __FUNCTION__);
-            return JNI_FALSE;
-        }
-        return JNI_TRUE;
+        return ret ? JNI_TRUE : JNI_FALSE;
     }
 #endif
     return JNI_FALSE;
diff --git a/core/res/res/drawable-hdpi/title_bar_medium.png b/core/res/res/drawable-hdpi/title_bar_medium.png
new file mode 100644
index 0000000..c13dd26
--- /dev/null
+++ b/core/res/res/drawable-hdpi/title_bar_medium.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_medium.png b/core/res/res/drawable-mdpi/title_bar_medium.png
new file mode 100644
index 0000000..9d01f79
--- /dev/null
+++ b/core/res/res/drawable-mdpi/title_bar_medium.png
Binary files differ
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index 8d7e470..e800dfa 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -19,17 +19,17 @@
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
-    android:background="@drawable/title_bar_tall"
+    android:background="@drawable/title_bar_medium"
     android:paddingRight="5dip"
     android:gravity="center_vertical">
     
-    <ImageView android:id="@+id/photo"
-        android:layout_width="56dip"
-        android:layout_height="62dip"
+    <android.widget.FasttrackBadgeWidget android:id="@+id/photo"
+        android:layout_alignParentLeft="true"
+        android:layout_centerVertical="true"
         android:layout_marginRight="10dip"
         android:layout_marginLeft="10dip"
-        android:scaleType="fitCenter"
-        android:background="@drawable/fasttrack_badge_middle_large"/>
+        style="@*android:style/Widget.FasttrackBadgeWidget.WindowSmall" />
+    />
     
     <LinearLayout
         android:layout_width="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a1a179b..eae838a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -530,6 +530,11 @@
              lines, the IME should provide multiple lines if it can.  Corresponds to
              {@link android.text.InputType#TYPE_TEXT_FLAG_IME_MULTI_LINE}. -->
         <flag name="textImeMultiLine" value="0x00040001" />
+        <!-- Can be combined with <var>text</var> and its variations to
+             indicate that the IME should not show any
+             dictionary-based word suggestions.  Corresponds to
+             {@link android.text.InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS}. -->
+        <flag name="textNoSuggestions" value="0x00080001" />
         <!-- Text that will be used as a URI.  Corresponds to
              {@link android.text.InputType#TYPE_CLASS_TEXT} |
              {@link android.text.InputType#TYPE_TEXT_VARIATION_URI}. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 7aaf218..365363a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -504,8 +504,10 @@
         <!-- The keyboard type has changed, for example the user has plugged
              in an external keyboard. -->
         <flag name="keyboard" value="0x0010" />
-        <!-- The keyboard accessibility has changed, for example the user has
-             slid the keyboard out to expose it. -->
+        <!-- The keyboard or navigation accessibility has changed, for example
+             the user has slid the keyboard out to expose it.  Note that
+             inspite of its name, this applied to any accessibility: keyboard
+             or navigation. -->
         <flag name="keyboardHidden" value="0x0020" />
         <!-- The navigation type has changed.  Should never normally happen. -->
         <flag name="navigation" value="0x0040" />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 62a230c..c967c4c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,7 +18,7 @@
 */
 -->
 <resources>
-	<drawable name="screen_background_light">#fff9f9f9</drawable>
+	<drawable name="screen_background_light">#ffffffff</drawable>
 	<drawable name="screen_background_dark">#ff202020</drawable>
     <drawable name="status_bar_closed_default_background">#ff000000</drawable>
     <drawable name="status_bar_opened_default_background">#ff000000</drawable>
@@ -45,7 +45,7 @@
     <color name="dim_foreground_dark_inverse">#323232</color>
     <color name="dim_foreground_dark_inverse_disabled">#80323232</color>
     <color name="hint_foreground_dark">#808080</color>
-    <color name="background_light">#fff9f9f9</color>
+    <color name="background_light">#ffffffff</color>
     <color name="bright_foreground_light">#ff000000</color>
     <color name="bright_foreground_light_inverse">#ffffffff</color>
     <color name="bright_foreground_light_disabled">#80000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 117e139..b710acb6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -35,6 +35,9 @@
     <!-- The duration (in milliseconds) of a long animation. -->
     <integer name="config_longAnimTime">300</integer>
 
+    <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
+         Please don't copy them, copy anything else. -->
+         
     <!-- This string array should be overridden by the device to present a list of network attributes.  This is used by the connectivity manager to decide which networks can coexist based on the hardward -->
     <!-- An Array of "[type-name],[associated radio-name],[priority]  -->
     <string-array translatable="false" name="networkAttributes">
@@ -53,18 +56,40 @@
         <item>"wifi,1,1"</item>
         <item>"mobile,0,1"</item>
     </string-array>
-
-    <!-- The number of degrees to rotate the display when the keyboard is open. -->
-    <integer name="config_lidOpenRotation">90</integer>
-
-    <!-- The number of degrees to rotate the display when the device is in a dock. -->
-    <integer name="config_dockedRotation">90</integer>
-
+    
     <!-- Flag indicating whether the keyguard should be bypassed when
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
     <bool name="config_bypass_keyguard_if_slider_open">true</bool>
     
+    <!-- Flag indicating whether the device supports automatic brightness mode. -->
+    <bool name="config_automatic_brightness_available">false</bool>
+    
+    <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
+
+    <!-- The number of degrees to rotate the display when the keyboard is open. -->
+    <integer name="config_lidOpenRotation">90</integer>
+
+    <!-- The number of degrees to rotate the display when the device is in a desk dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_deskDockRotation">-1</integer>
+
+    <!-- The number of degrees to rotate the display when the device is in a car dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_carDockRotation">-1</integer>
+
+    <!-- Indicate whether the lid state impacts the accessibility of
+         the physical keyboard.  0 means it doesn't, 1 means it is accessible
+         when the lid is open, 2 means it is accessible when the lid is
+         closed.  The default is 1. -->
+    <integer name="config_lidKeyboardAccessibility">1</integer>
+
+    <!-- Indicate whether the lid state impacts the accessibility of
+         the physical keyboard.  0 means it doesn't, 1 means it is accessible
+         when the lid is open, 2 means it is accessible when the lid is
+         closed.  The default is 0. -->
+    <integer name="config_lidNavigationAccessibility">0</integer>
+
     <!-- Vibrator pattern for feedback about a long screen/key press -->
     <integer-array name="config_longPressVibePattern">
         <item>0</item>
@@ -81,6 +106,4 @@
         <item>30</item>
     </integer-array>
     
-    <!-- Flag indicating whether the device supports automatic brightness mode. -->
-    <bool name="config_automatic_brightness_available">false</bool>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 69ddd63..bd79c75 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1962,7 +1962,7 @@
     <string name="allow">Allow</string>
     <string name="deny">Deny</string>
     <string name="permission_request_notification_title">Permission Requested</string>
-    <string name="permission_request_notification_subtitle">for account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
+    <string name="permission_request_notification_with_subtitle">Permission Requested\nfor account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
 
     <!-- Label to show for a service that is running because it is an input method. -->
     <string name="input_method_binding_label">Input method</string>
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index a32d8ea..041c5d3 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -32,3 +32,20 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 
 include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := required_hardware.xml
+
+LOCAL_MODULE_TAGS := user
+
+LOCAL_MODULE_CLASS := ETC
+
+# This will install the file in /system/etc/permissions
+#
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
diff --git a/data/etc/android.hardware.camera.flash-autofocus.xml b/data/etc/android.hardware.camera.flash-autofocus.xml
new file mode 100644
index 0000000..55f1900
--- /dev/null
+++ b/data/etc/android.hardware.camera.flash-autofocus.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard set of features for a camera with a flash.  Note
+     that this currently requires having auto-focus as well. -->
+<permissions>
+    <feature name="android.hardware.camera" />
+    <feature name="android.hardware.camera.autofocus" />
+    <feature name="android.hardware.camera.flash" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.light.xml b/data/etc/android.hardware.sensor.light.xml
new file mode 100644
index 0000000..78b0fec
--- /dev/null
+++ b/data/etc/android.hardware.sensor.light.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<!-- Feature for devices with an ambient light sensor. -->
+<permissions>
+    <feature name="android.hardware.sensor.light" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.proximity.xml b/data/etc/android.hardware.sensor.proximity.xml
new file mode 100644
index 0000000..d1948de
--- /dev/null
+++ b/data/etc/android.hardware.sensor.proximity.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<!-- Feature for devices with a proximity sensor. -->
+<permissions>
+    <feature name="android.hardware.sensor.proximity" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.cdma.xml b/data/etc/android.hardware.telephony.cdma.xml
new file mode 100644
index 0000000..72e0485
--- /dev/null
+++ b/data/etc/android.hardware.telephony.cdma.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<!-- This is the standard set of features for a CDMA phone. -->
+<permissions>
+    <feature name="android.hardware.telephony" />
+    <feature name="android.hardware.telephony.cdma" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.gsm.xml b/data/etc/android.hardware.telephony.gsm.xml
new file mode 100644
index 0000000..ffde433
--- /dev/null
+++ b/data/etc/android.hardware.telephony.gsm.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<!-- This is the standard set of features for a GSM phone. -->
+<permissions>
+    <feature name="android.hardware.telephony" />
+    <feature name="android.hardware.telephony.gsm" />
+</permissions>
diff --git a/data/etc/required_hardware.xml b/data/etc/required_hardware.xml
new file mode 100644
index 0000000..896a148
--- /dev/null
+++ b/data/etc/required_hardware.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<!-- These are the hardware features that all devices must possess.
+     These are always added for you by the build system, you do not need
+     to add them yourself. -->
+<permissions>
+    <feature name="android.hardware.sensor.compass" />
+    <feature name="android.hardware.sensor.accelerometer" />
+    <feature name="android.hardware.bluetooth" />
+    <feature name="android.hardware.wifi" />
+</permissions>
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
index 85b89d1..ff9579f 100755
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -441,7 +441,7 @@
 <pre>
 MyApp/
     res/
-        drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-dpad-480x320/
+        drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-navexposed-dpad-480x320/
 </pre>
 
 <p>More typically, you will only specify a few specific configuration options. You may drop any of the values from the
@@ -575,6 +575,14 @@
         <td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>
     </tr>
     <tr>
+        <td>Whether the navigation keys are available to the user</td>
+        <td><p><code>navexposed</code>, <code>navhidden</code>
+        </p><p>
+          If the hardware's navigation keys are currently available to
+          the user, the navexposed resources will be used; if they are not
+          available (such as behind a closed lid), navhidden will be used.</p></td>
+    </tr>
+    <tr>
         <td>Primary non-touchscreen<br />
             navigation method</td>
         <td><code>nonav</code>, <code>dpad</code>, <code>trackball</code>, <code>wheel</code> </td>
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 3266f1e..c6f57d4 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -36,7 +36,6 @@
     private Drawable mCurrDrawable;
     private int mAlpha = 0xFF;
     private ColorFilter mColorFilter;
-    private boolean mDither = DEFAULT_DITHER;
 
     private int mCurIndex = -1;
     private boolean mMutated;
@@ -83,10 +82,10 @@
 
     @Override
     public void setDither(boolean dither) {
-        if (mDither != dither) {
-            mDither = dither;
+        if (mDrawableContainerState.mDither != dither) {
+            mDrawableContainerState.mDither = dither;
             if (mCurrDrawable != null) {
-                mCurrDrawable.setDither(mDither);
+                mCurrDrawable.setDither(mDrawableContainerState.mDither);
             }
         }
     }
@@ -212,7 +211,7 @@
             if (d != null) {
                 d.setVisible(isVisible(), true);
                 d.setAlpha(mAlpha);
-                d.setDither(mDither);
+                d.setDither(mDrawableContainerState.mDither);
                 d.setColorFilter(mColorFilter);
                 d.setState(getState());
                 d.setLevel(getLevel());
@@ -285,6 +284,8 @@
         boolean     mCanConstantState;
 
         boolean     mPaddingChecked = false;
+        
+        boolean     mDither = DEFAULT_DITHER;        
 
         DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
                 Resources res) {
@@ -323,6 +324,8 @@
                 mOpacity = orig.mOpacity;
                 mHaveStateful = orig.mHaveStateful;
                 mStateful = orig.mStateful;
+                
+                mDither = orig.mDither;
 
             } else {
                 mDrawables = new Drawable[10];
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 89db4fa..d35c5e3 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -140,6 +140,8 @@
     native void nScriptSetTimeZone(int script, byte[] timeZone);
     native void nScriptSetType(int type, boolean writable, String name, int slot);
     native void nScriptSetRoot(boolean isRoot);
+    native void nScriptSetInvokable(String name, int slot);
+    native void nScriptInvoke(int id, int slot);
 
     native void nScriptCBegin();
     native void nScriptCSetScript(byte[] script, int offset, int length);
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index a402471..35791a3 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -25,6 +25,22 @@
     boolean mIsRoot;
     Type[] mTypes;
     boolean[] mWritable;
+    Invokable[] mInvokables;
+
+    public static class Invokable {
+        RenderScript mRS;
+        Script mScript;
+        int mSlot;
+        String mName;
+
+        Invokable() {
+            mSlot = -1;
+        }
+
+        public void execute() {
+            mRS.nScriptInvoke(mScript.mID, mSlot);
+        }
+    }
 
     Script(int id, RenderScript rs) {
         super(rs);
@@ -61,12 +77,15 @@
         Type[] mTypes;
         String[] mNames;
         boolean[] mWritable;
+        int mInvokableCount = 0;
+        Invokable[] mInvokables;
 
         Builder(RenderScript rs) {
             mRS = rs;
             mTypes = new Type[MAX_SLOT];
             mNames = new String[MAX_SLOT];
             mWritable = new boolean[MAX_SLOT];
+            mInvokables = new Invokable[MAX_SLOT];
         }
 
         public void setType(Type t, int slot) {
@@ -79,6 +98,15 @@
             mNames[slot] = name;
         }
 
+        public Invokable addInvokable(String func) {
+            Invokable i = new Invokable();
+            i.mName = func;
+            i.mRS = mRS;
+            i.mSlot = mInvokableCount;
+            mInvokables[mInvokableCount++] = i;
+            return i;
+        }
+
         public void setType(boolean writable, int slot) {
             mWritable[slot] = writable;
         }
@@ -90,11 +118,20 @@
                     mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct);
                 }
             }
+            for(int ct=0; ct < mInvokableCount; ct++) {
+                mRS.nScriptSetInvokable(mInvokables[ct].mName, ct);
+            }
         }
 
         void transferObject(Script s) {
             s.mIsRoot = mIsRoot;
             s.mTypes = mTypes;
+            s.mInvokables = new Invokable[mInvokableCount];
+            for(int ct=0; ct < mInvokableCount; ct++) {
+                s.mInvokables[ct] = mInvokables[ct];
+                s.mInvokables[ct].mScript = s;
+            }
+            s.mInvokables = null;
         }
 
         public void setRoot(boolean r) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 90b5958..eae6f24 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -891,6 +891,29 @@
 }
 
 static void
+nScriptSetInvoke(JNIEnv *_env, jobject _this, jstring _str, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptSetInvoke, con(%p)", con);
+    const char* n = NULL;
+    if (_str) {
+        n = _env->GetStringUTFChars(_str, NULL);
+    }
+    rsScriptSetInvoke(con, n, slot);
+    if (n) {
+        _env->ReleaseStringUTFChars(_str, n);
+    }
+}
+
+static void
+nScriptInvoke(JNIEnv *_env, jobject _this, jint obj, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj);
+    rsScriptInvoke(con, (RsScript)obj, slot);
+}
+
+static void
 nScriptSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -1366,6 +1389,8 @@
 {"nScriptSetTimeZone",             "(I[B)V",                               (void*)nScriptSetTimeZone },
 {"nScriptSetType",                 "(IZLjava/lang/String;I)V",             (void*)nScriptSetType },
 {"nScriptSetRoot",                 "(Z)V",                                 (void*)nScriptSetRoot },
+{"nScriptSetInvokable",            "(Ljava/lang/String;I)V",               (void*)nScriptSetInvoke },
+{"nScriptInvoke",                  "(II)V",                                (void*)nScriptInvoke },
 
 {"nScriptCBegin",                  "()V",                                  (void*)nScriptCBegin },
 {"nScriptCSetScript",              "([BII)V",                              (void*)nScriptCSetScript },
diff --git a/include/media/stagefright/SoftwareRenderer.h b/include/media/stagefright/SoftwareRenderer.h
index b61858c..1545493 100644
--- a/include/media/stagefright/SoftwareRenderer.h
+++ b/include/media/stagefright/SoftwareRenderer.h
@@ -45,6 +45,7 @@
 
     void renderCbYCrY(const void *data, size_t size);
     void renderYUV420Planar(const void *data, size_t size);
+    void renderQCOMYUV420SemiPlanar(const void *data, size_t size);
 
     OMX_COLOR_FORMATTYPE mColorFormat;
     sp<ISurface> mISurface;
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index e524e2a..17ccad6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -864,6 +864,13 @@
         KEYSHIDDEN_SOFT = 0x0003,
     };
     
+    enum {
+        MASK_NAVHIDDEN = 0x000c,
+        NAVHIDDEN_ANY = 0x0000,
+        NAVHIDDEN_NO = 0x0004,
+        NAVHIDDEN_YES = 0x0008,
+    };
+    
     union {
         struct {
             uint8_t keyboard;
@@ -1011,7 +1018,8 @@
         if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
         if (density != o.density) diffs |= CONFIG_DENSITY;
         if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
-        if (((inputFlags^o.inputFlags)&MASK_KEYSHIDDEN) != 0) diffs |= CONFIG_KEYBOARD_HIDDEN;
+        if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0)
+                diffs |= CONFIG_KEYBOARD_HIDDEN;
         if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD;
         if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
@@ -1082,6 +1090,11 @@
                 if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
 
+            if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) {
+                if (!(inputFlags & MASK_NAVHIDDEN)) return false;
+                if (!(o.inputFlags & MASK_NAVHIDDEN)) return true;
+            }
+
             if (keyboard != o.keyboard) {
                 if (!keyboard) return false;
                 if (!o.keyboard) return true;
@@ -1225,6 +1238,18 @@
                     }
                 }
 
+                const int navHidden = inputFlags & MASK_NAVHIDDEN;
+                const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN;
+                if (navHidden != oNavHidden) {
+                    const int reqNavHidden =
+                            requested->inputFlags & MASK_NAVHIDDEN;
+                    if (reqNavHidden) {
+
+                        if (!navHidden) return false;
+                        if (!oNavHidden) return true;
+                    }
+                }
+
                 if ((keyboard != o.keyboard) && requested->keyboard) {
                     return (keyboard);
                 }
@@ -1332,6 +1357,12 @@
                     return false;
                 }
             }
+            const int navHidden = inputFlags&MASK_NAVHIDDEN;
+            const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
+            if (setNavHidden != 0 && navHidden != 0
+                && navHidden != setNavHidden) {
+                return false;
+            }
             if (settings.keyboard != 0 && keyboard != 0
                 && keyboard != settings.keyboard) {
                 return false;
diff --git a/keystore/java/android/security/ServiceCommand.java b/keystore/java/android/security/ServiceCommand.java
index ee80014..9923011 100644
--- a/keystore/java/android/security/ServiceCommand.java
+++ b/keystore/java/android/security/ServiceCommand.java
@@ -49,8 +49,6 @@
 
     public static final int BUFFER_LENGTH = 4096;
 
-    private static final boolean DBG = true;
-
     private String mServiceName;
     private String mTag;
     private InputStream mIn;
@@ -61,7 +59,6 @@
         if (mSocket != null) {
             return true;
         }
-        if (DBG) Log.d(mTag, "connecting...");
         try {
             mSocket = new LocalSocket();
 
@@ -80,7 +77,6 @@
     }
 
     private void disconnect() {
-        if (DBG) Log.d(mTag,"disconnecting...");
         try {
             if (mSocket != null) mSocket.close();
         } catch (IOException ex) { }
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 4f7500f..add358b 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2069,7 +2069,7 @@
    }
 }
 
-AudioFlinger::PlaybackThread::TrackBase::~TrackBase()
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
 {
     if (mCblk) {
         mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
@@ -2081,7 +2081,7 @@
     mClient.clear();
 }
 
-void AudioFlinger::PlaybackThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->raw = 0;
     mFrameCount = buffer->frameCount;
@@ -2089,7 +2089,7 @@
     buffer->frameCount = 0;
 }
 
-bool AudioFlinger::PlaybackThread::TrackBase::step() {
+bool AudioFlinger::ThreadBase::TrackBase::step() {
     bool result;
     audio_track_cblk_t* cblk = this->cblk();
 
@@ -2101,7 +2101,7 @@
     return result;
 }
 
-void AudioFlinger::PlaybackThread::TrackBase::reset() {
+void AudioFlinger::ThreadBase::TrackBase::reset() {
     audio_track_cblk_t* cblk = this->cblk();
 
     cblk->user = 0;
@@ -2112,20 +2112,20 @@
     LOGV("TrackBase::reset");
 }
 
-sp<IMemory> AudioFlinger::PlaybackThread::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
 {
     return mCblkMemory;
 }
 
-int AudioFlinger::PlaybackThread::TrackBase::sampleRate() const {
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
     return (int)mCblk->sampleRate;
 }
 
-int AudioFlinger::PlaybackThread::TrackBase::channelCount() const {
+int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
     return (int)mCblk->channels;
 }
 
-void* AudioFlinger::PlaybackThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
     audio_track_cblk_t* cblk = this->cblk();
     int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
     int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index ac2e738..87ad97c 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -297,6 +297,16 @@
 	param const char * name
 	}
 
+ScriptSetInvoke {
+	param const char * name
+	param uint32_t slot
+	}
+
+ScriptInvoke {
+	param RsScript s
+	param uint32_t slot
+	}
+
 ScriptSetRoot {
 	param bool isRoot
 	}
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index fde31a1..99a085d 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -27,6 +27,8 @@
     mEnviroment.mClearColor[2] = 0;
     mEnviroment.mClearColor[3] = 1;
     mEnviroment.mClearDepth = 1;
+    mEnviroment.mClearStencil = 0;
+    mEnviroment.mIsRoot = false;
 }
 
 Script::~Script()
@@ -83,10 +85,23 @@
     }
 }
 
+void rsi_ScriptSetInvoke(Context *rsc, const char *name, uint32_t slot)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mInvokableNames[slot] = name;
+}
+
+void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot)
+{
+    Script *s = static_cast<Script *>(vs);
+    s->mEnviroment.mInvokables[slot]();
+}
+
+
 void rsi_ScriptSetRoot(Context * rsc, bool isRoot)
 {
     ScriptCState *ss = &rsc->mScriptC;
-    ss->mEnviroment.mIsRoot = isRoot;
+    ss->mScript->mEnviroment.mIsRoot = isRoot;
 }
 
 
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 60f83a6..e40531e 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -34,6 +34,7 @@
 class Script : public ObjectBase
 {
 public:
+    typedef void (* InvokeFunc_t)(void);
 
     Script();
     virtual ~Script();
@@ -52,17 +53,22 @@
         ObjectBaseRef<ProgramFragment> mFragment;
         //ObjectBaseRef<ProgramRaster> mRaster;
         ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
-
+        InvokeFunc_t mInvokables[MAX_SCRIPT_BANKS];
+        const char * mScriptText;
+        uint32_t mScriptTextLength;
     };
     Enviroment_t mEnviroment;
 
     uint32_t mCounstantBufferCount;
 
+
     ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS];
     ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS];
     String8 mSlotNames[MAX_SCRIPT_BANKS];
     bool mSlotWritable[MAX_SCRIPT_BANKS];
 
+
+
     virtual bool run(Context *, uint32_t launchID) = 0;
 };
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 8230cbc..108ae5a 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -82,36 +82,27 @@
 
 ScriptCState::ScriptCState()
 {
+    mScript = NULL;
     clear();
 }
 
 ScriptCState::~ScriptCState()
 {
-    if (mAccScript) {
-        accDeleteScript(mAccScript);
-    }
+    delete mScript;
+    mScript = NULL;
 }
 
 void ScriptCState::clear()
 {
-    memset(&mProgram, 0, sizeof(mProgram));
-
     for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         mConstantBufferTypes[ct].clear();
         mSlotNames[ct].setTo("");
+        mInvokableNames[ct].setTo("");
         mSlotWritable[ct] = false;
     }
 
-    memset(&mEnviroment, 0, sizeof(mEnviroment));
-    mEnviroment.mClearColor[0] = 0;
-    mEnviroment.mClearColor[1] = 0;
-    mEnviroment.mClearColor[2] = 0;
-    mEnviroment.mClearColor[3] = 1;
-    mEnviroment.mClearDepth = 1;
-    mEnviroment.mClearStencil = 0;
-    mEnviroment.mIsRoot = false;
-
-    mAccScript = NULL;
+    delete mScript;
+    mScript = new ScriptC();
 
     mInt32Defines.clear();
     mFloatDefines.clear();
@@ -127,9 +118,9 @@
     return NULL;
 }
 
-void ScriptCState::runCompiler(Context *rsc)
+void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
 {
-    mAccScript = accCreateScript();
+    s->mAccScript = accCreateScript();
     String8 tmp;
 
     rsc->appendNameDefines(&tmp);
@@ -139,44 +130,51 @@
     appendTypes(&tmp);
     tmp.append("#line 1\n");
 
-    const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
-    int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
-    accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
-    accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
-    accCompileScript(mAccScript);
-    accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
-    accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit);
-    rsAssert(mProgram.mScript);
+    const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText};
+    int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ;
+    accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
+    accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL);
+    accCompileScript(s->mAccScript);
+    accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript);
+    accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit);
+    rsAssert(s->mProgram.mScript);
 
-    if (!mProgram.mScript) {
+    if (!s->mProgram.mScript) {
         ACCchar buf[4096];
         ACCsizei len;
-        accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
+        accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf);
         LOGE(buf);
     }
 
-    if (mProgram.mInit) {
-        mProgram.mInit();
+    if (s->mProgram.mInit) {
+        s->mProgram.mInit();
     }
 
     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         if (mSlotNames[ct].length() > 0) {
-            accGetScriptLabel(mAccScript,
+            accGetScriptLabel(s->mAccScript,
                               mSlotNames[ct].string(),
-                              (ACCvoid**) &mProgram.mSlotPointers[ct]);
-            LOGE("var  %s  %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]);
+                              (ACCvoid**) &s->mProgram.mSlotPointers[ct]);
         }
     }
 
-    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
-    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
-    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
+    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        if (mInvokableNames[ct].length() > 0) {
+            accGetScriptLabel(s->mAccScript,
+                              mInvokableNames[ct].string(),
+                              (ACCvoid**) &s->mEnviroment.mInvokables[ct]);
+        }
+    }
 
-    if (mProgram.mScript) {
+    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
+    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
+    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
+
+    if (s->mProgram.mScript) {
         const static int pragmaMax = 16;
         ACCsizei pragmaCount;
         ACCchar * str[pragmaMax];
-        accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
+        accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]);
 
         for (int ct=0; ct < pragmaCount; ct+=2) {
             if (!strcmp(str[ct], "version")) {
@@ -188,12 +186,12 @@
                     continue;
                 }
                 if (!strcmp(str[ct+1], "parent")) {
-                    mEnviroment.mVertex.clear();
+                    s->mEnviroment.mVertex.clear();
                     continue;
                 }
                 ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
                 if (pv != NULL) {
-                    mEnviroment.mVertex.set(pv);
+                    s->mEnviroment.mVertex.set(pv);
                     continue;
                 }
                 LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
@@ -208,12 +206,12 @@
                     continue;
                 }
                 if (!strcmp(str[ct+1], "parent")) {
-                    mEnviroment.mFragment.clear();
+                    s->mEnviroment.mFragment.clear();
                     continue;
                 }
                 ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
                 if (pf != NULL) {
-                    mEnviroment.mFragment.set(pf);
+                    s->mEnviroment.mFragment.set(pf);
                     continue;
                 }
                 LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
@@ -224,13 +222,13 @@
                     continue;
                 }
                 if (!strcmp(str[ct+1], "parent")) {
-                    mEnviroment.mFragmentStore.clear();
+                    s->mEnviroment.mFragmentStore.clear();
                     continue;
                 }
                 ProgramFragmentStore * pfs =
                     (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
                 if (pfs != NULL) {
-                    mEnviroment.mFragmentStore.set(pfs);
+                    s->mEnviroment.mFragmentStore.set(pfs);
                     continue;
                 }
                 LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
@@ -351,33 +349,6 @@
             s.append(";\n");
             LOGD(s);
             str->append(s);
-#if 0
-            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
-                const Component *c = e->getComponent(ct2);
-                tmp.setTo("#define ");
-                tmp.append(mSlotNames[ct]);
-                tmp.append("_");
-                tmp.append(c->getComponentName());
-                switch (c->getType()) {
-                case Component::FLOAT:
-                    tmp.append(" loadF(");
-                    break;
-                case Component::SIGNED:
-                    sprintf(buf, " loadI%i(", c->getBits());
-                    tmp.append(buf);
-                    break;
-                case Component::UNSIGNED:
-                    sprintf(buf, " loadU%i(", c->getBits());
-                    tmp.append(buf);
-                    break;
-                }
-                sprintf(buf, "%i, %i)\n", ct, ct2);
-                tmp.append(buf);
-
-                LOGD(tmp);
-                str->append(tmp);
-            }
-#endif
         }
     }
 }
@@ -394,15 +365,16 @@
 
 void rsi_ScriptCSetScript(Context * rsc, void *vp)
 {
-    ScriptCState *ss = &rsc->mScriptC;
-    ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
+    rsAssert(0);
+    //ScriptCState *ss = &rsc->mScriptC;
+    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
 }
 
 void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
 {
     ScriptCState *ss = &rsc->mScriptC;
-    ss->mProgram.mScriptText = text;
-    ss->mProgram.mScriptTextLength = len;
+    ss->mScript->mEnviroment.mScriptText = text;
+    ss->mScript->mEnviroment.mScriptTextLength = len;
 }
 
 
@@ -410,14 +382,11 @@
 {
     ScriptCState *ss = &rsc->mScriptC;
 
-    ss->runCompiler(rsc);
+    ScriptC *s = ss->mScript;
+    ss->mScript = NULL;
 
-    ScriptC *s = new ScriptC();
+    ss->runCompiler(rsc, s);
     s->incUserRef();
-    s->mAccScript = ss->mAccScript;
-    ss->mAccScript = NULL;
-    s->mEnviroment = ss->mEnviroment;
-    s->mProgram = ss->mProgram;
     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
         s->mSlotNames[ct] = ss->mSlotNames[ct];
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 8aa99ef..355f0c3 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -67,17 +67,15 @@
     ScriptCState();
     ~ScriptCState();
 
-    ACCscript* mAccScript;
-
-    ScriptC::Program_t mProgram;
-    Script::Enviroment_t mEnviroment;
+    ScriptC *mScript;
 
     ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS];
     String8 mSlotNames[MAX_SCRIPT_BANKS];
     bool mSlotWritable[MAX_SCRIPT_BANKS];
+    String8 mInvokableNames[MAX_SCRIPT_BANKS];
 
     void clear();
-    void runCompiler(Context *rsc);
+    void runCompiler(Context *rsc, ScriptC *s);
     void appendVarDefines(String8 *str);
     void appendTypes(String8 *str);
 
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
index 5dc0ba0..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -111,6 +111,50 @@
     }
 };
 
+template <int FACTOR = 0>
+struct BlurColor888X
+{
+    typedef uint32_t type;
+    int r, g, b;    
+    inline BlurColor888X() { }
+    inline BlurColor888X(uint32_t v) {
+        v = BLUR_RGBA_TO_HOST(v);
+        r = v & 0xFF;
+        g = (v >>  8) & 0xFF;
+        b = (v >> 16) & 0xFF;
+    }
+    inline void clear() { r=g=b=0; }
+    inline uint32_t to(int shift, int last, int dither) const {
+        int R = r;
+        int G = g;
+        int B = b;
+        if  (UNLIKELY(last)) {
+            if (FACTOR>0) {
+                int L = (R+G+G+B)>>2;
+                R += ((L - R) * FACTOR) >> 8;
+                G += ((L - G) * FACTOR) >> 8;
+                B += ((L - B) * FACTOR) >> 8;
+            }
+        }
+        R >>= shift;
+        G >>= shift;
+        B >>= shift;
+        return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
+    }    
+    inline BlurColor888X& operator += (const BlurColor888X& rhs) {
+        r += rhs.r;
+        g += rhs.g;
+        b += rhs.b;
+        return *this;
+    }
+    inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
+        r -= rhs.r;
+        g -= rhs.g;
+        b -= rhs.b;
+        return *this;
+    }
+};
+
 struct BlurGray565
 {
     typedef uint16_t type;
@@ -316,7 +360,13 @@
         int kernelSizeUser,
         int repeat)
 {
-    return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    status_t err = BAD_VALUE;
+    if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
+        err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+    } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
+        err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
+    }
+    return err;
 }
 
 } // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index d893f0a..cc913cbd 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -174,6 +174,13 @@
 
     surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
 
+    if (mFlags & UPDATE_ON_DEMAND) {
+        // if we have update on demand, we definitely don't need to
+        // preserve the backbuffer, which is usually costly.
+        eglSurfaceAttrib(display, surface,
+                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+    }
+
     if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
         if (dummy == EGL_BUFFER_PRESERVED) {
             mFlags |= BUFFER_PRESERVED;
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 1e7f1e6..7387c85 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -303,7 +303,6 @@
 
     // Index of the back buffer
     const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
-
     if (backbufferChanged) {
         // the size changed, we need to ask our client to request a new buffer
         LOGD_IF(DEBUG_RESIZE,
@@ -318,17 +317,6 @@
         // buffer, it'll get the new size.
         setDrawingSize(temp.w, temp.h);
 
-        // all buffers need reallocation
-        lcblk->reallocate();
-
-        // recompute the visible region
-        // FIXME: ideally we would do that only when we have received
-        // a buffer of the right size
-        flags |= Layer::eVisibleRegion;
-        this->contentDirty = true;
-        
-#if 0 
-        // FIXME: handle freeze lock
         // we're being resized and there is a freeze display request,
         // acquire a freeze lock, so that the screen stays put
         // until we've redrawn at the new size; this is to avoid
@@ -340,7 +328,12 @@
                 mFreezeLock = mFlinger->getFreezeLock();
             }
         }
-#endif
+
+        // recompute the visible region
+        flags |= Layer::eVisibleRegion;
+        this->contentDirty = true;
+        // all buffers need reallocation
+        lcblk->reallocate();
     }
 
     if (temp.sequence != front.sequence) {
@@ -382,6 +375,13 @@
     const Region dirty(lcblk->getDirtyRegion(buf));
     mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
 
+
+    const Layer::State& front(drawingState());
+    if (newFrontBuffer->getWidth() == front.w &&
+        newFrontBuffer->getHeight() ==front.h) {
+        mFreezeLock.clear();
+    }
+
     // FIXME: signal an event if we have more buffers waiting
     // mFlinger->signalEvent();
 
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index e14f35b..0ef663f 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -40,9 +40,9 @@
 
 LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client, int32_t i)
-     : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
-     mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
-     mWidthScale(1.0f), mHeightScale(1.0f)
+: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+mRefreshCache(true), mCacheAge(0), mTextureName(-1U), 
+mWidthScale(1.0f), mHeightScale(1.0f)
 {
 }
 
@@ -136,6 +136,13 @@
         // create the texture name the first time
         // can't do that in the ctor, because it runs in another thread.
         glGenTextures(1, &mTextureName);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
+        glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
+        if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
+            mReadFormat = GL_RGBA;
+            mReadType = GL_UNSIGNED_BYTE;
+            mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+        }
     }
 
     Region::const_iterator it = clip.begin();
@@ -143,33 +150,39 @@
     if (it != end) {
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, mTextureName);
-    
+
         if (mRefreshCache) {
             mRefreshCache = false;
             mAutoRefreshPending = false;
-            
-            // allocate enough memory for 4-bytes (2 pixels) aligned data
-            const int32_t s = (w + 1) & ~1;
-            uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+            int32_t pixelSize = 4;
+            int32_t s = w;
+            if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
+                // allocate enough memory for 4-bytes (2 pixels) aligned data
+                s = (w + 1) & ~1;
+                pixelSize = 2;
+            }
+
+            uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
 
             // This reads the frame-buffer, so a h/w GL would have to
             // finish() its rendering first. we don't want to do that
             // too often. Read data is 4-bytes aligned.
-            glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
-            
+            glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
+
             // blur that texture.
             GGLSurface bl;
             bl.version = sizeof(GGLSurface);
             bl.width = w;
             bl.height = h;
             bl.stride = s;
-            bl.format = GGL_PIXEL_FORMAT_RGB_565;
+            bl.format = mBlurFormat;
             bl.data = (GGLubyte*)pixels;            
             blurFilter(&bl, 8, 2);
 
             if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
-                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
+                        mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / w;
                 mHeightScale =-1.0f / h;
                 mYOffset = 0;
@@ -178,10 +191,10 @@
                 GLuint th = 1 << (31 - clz(h));
                 if (tw < w) tw <<= 1;
                 if (th < h) th <<= 1;
-                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0,
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+                glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
+                        mReadFormat, mReadType, NULL);
                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, 
-                        GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+                        mReadFormat, mReadType, pixels);
                 mWidthScale  = 1.0f / tw;
                 mHeightScale =-1.0f / th;
                 mYOffset = th-h;
@@ -189,7 +202,7 @@
 
             free((void*)pixels);
         }
-        
+
         const State& s = drawingState();
         if (UNLIKELY(s.alpha < 0xFF)) {
             const GGLfixed alpha = (s.alpha << 16)/255;
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index bf36ae4..2e9d7c6 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -59,6 +59,9 @@
     mutable GLfloat mWidthScale;
     mutable GLfloat mHeightScale;
     mutable GLfloat mYOffset;
+    mutable GLint   mReadFormat;
+    mutable GLint   mReadType;
+    mutable uint32_t mBlurFormat;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 38a897d..667571b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -595,6 +595,7 @@
 
     *overlayRef = new OverlayRef(mOverlayHandle, channel,
             mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+    mLayer.mFlinger->signalEvent();
 }
 
 LayerBuffer::OverlaySource::~OverlaySource()
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1dd644b..d6463a1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -345,6 +345,9 @@
 
     /**
      * Adjusts the volume of a particular stream by one step in a direction.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
      * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
@@ -370,6 +373,9 @@
      * active, it will have the highest priority regardless of if the in-call
      * screen is showing. Another example, if music is playing in the background
      * and a call is not active, the music stream will be adjusted.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param direction The direction to adjust the volume. One of
      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -391,6 +397,9 @@
     /**
      * Adjusts the volume of the most relevant stream, or the given fallback
      * stream.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param direction The direction to adjust the volume. One of
      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -541,6 +550,9 @@
      * <p>
      * For a better user experience, applications MUST unmute a muted stream
      * in onPause() and mute is again in onResume() if appropriate.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param streamType The stream to be muted/unmuted.
      * @param state The required mute state: true for mute ON, false for mute OFF
@@ -608,6 +620,9 @@
 
     /**
      * Sets the setting for when the vibrate type should vibrate.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param vibrateType The type of vibrate. One of
      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
@@ -630,6 +645,9 @@
 
     /**
      * Sets the speakerphone on or off.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to turn on speakerphone;
      *           <var>false</var> to turn it off
@@ -660,6 +678,9 @@
 
     /**
      * Request use of Bluetooth SCO headset for communications.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to use bluetooth SCO for communications;
      *               <var>false</var> to not use bluetooth SCO for communications
@@ -739,6 +760,9 @@
 
     /**
      * Sets the microphone mute on or off.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to mute the microphone;
      *           <var>false</var> to turn mute off
@@ -758,6 +782,13 @@
 
     /**
      * Sets the audio mode.
+     * <p>
+     * The audio mode encompasses audio routing AND the behavior of
+     * the telephony layer. Therefore this method should only be used by applications that
+     * replace the platform-wide management of audio settings or the main telephony application.
+     * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
+     * application when it places a phone call, as it will cause signals from the radio layer
+     * to feed the platform mixer.
      *
      * @param mode  the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
      *              Informs the HAL about the current audio state so that
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index aba40b3..73b6483 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,8 +16,7 @@
 
 package android.media;
 
-import android.util.Log;
-
+import java.io.IOException;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -25,171 +24,102 @@
 import java.util.Map;
 
 /**
- * Wrapper for native Exif library
- * {@hide}
+ * This is a class for reading and writing Exif tags in a JPEG file.
  */
 public class ExifInterface {
-    private static final String TAG = "ExifInterface";
-    private String mFilename;
-
-    // Constants used for the Orientation Exif tag.
-    public static final int ORIENTATION_UNDEFINED = 0;
-    public static final int ORIENTATION_NORMAL = 1;
-
-    // Constants used for white balance
-    public static final int WHITEBALANCE_AUTO = 0;
-    public static final int WHITEBALANCE_MANUAL = 1;
-
-    // left right reversed mirror
-    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
-    public static final int ORIENTATION_ROTATE_180 = 3;
-
-    // upside down mirror
-    public static final int ORIENTATION_FLIP_VERTICAL = 4;
-
-    // flipped about top-left <--> bottom-right axis
-    public static final int ORIENTATION_TRANSPOSE = 5;
-
-    // rotate 90 cw to right it
-    public static final int ORIENTATION_ROTATE_90 = 6;
-
-    // flipped about top-right <--> bottom-left axis
-    public static final int ORIENTATION_TRANSVERSE = 7;
-
-    // rotate 270 to right it
-    public static final int ORIENTATION_ROTATE_270 = 8;
 
     // The Exif tag names
     public static final String TAG_ORIENTATION = "Orientation";
-
     public static final String TAG_DATETIME = "DateTime";
     public static final String TAG_MAKE = "Make";
     public static final String TAG_MODEL = "Model";
     public static final String TAG_FLASH = "Flash";
     public static final String TAG_IMAGE_WIDTH = "ImageWidth";
     public static final String TAG_IMAGE_LENGTH = "ImageLength";
-
     public static final String TAG_GPS_LATITUDE = "GPSLatitude";
     public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
-
     public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
     public static final String TAG_WHITE_BALANCE = "WhiteBalance";
 
-    private boolean mSavedAttributes = false;
-    private boolean mHasThumbnail = false;
-    private HashMap<String, String> mCachedAttributes = null;
+    // Constants used for the Orientation Exif tag.
+    public static final int ORIENTATION_UNDEFINED = 0;
+    public static final int ORIENTATION_NORMAL = 1;
+    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;  // left right reversed mirror
+    public static final int ORIENTATION_ROTATE_180 = 3;
+    public static final int ORIENTATION_FLIP_VERTICAL = 4;  // upside down mirror
+    public static final int ORIENTATION_TRANSPOSE = 5;  // flipped about top-left <--> bottom-right axis
+    public static final int ORIENTATION_ROTATE_90 = 6;  // rotate 90 cw to right it
+    public static final int ORIENTATION_TRANSVERSE = 7;  // flipped about top-right <--> bottom-left axis
+    public static final int ORIENTATION_ROTATE_270 = 8;  // rotate 270 to right it
+
+    // Constants used for white balance
+    public static final int WHITEBALANCE_AUTO = 0;
+    public static final int WHITEBALANCE_MANUAL = 1;
 
     static {
         System.loadLibrary("exif");
     }
 
-    private static ExifInterface sExifObj = null;
-    /**
-     * Since the underlying jhead native code is not thread-safe,
-     * ExifInterface should use singleton interface instead of public
-     * constructor.
-     */
-    private static synchronized ExifInterface instance() {
-        if (sExifObj == null) {
-            sExifObj = new ExifInterface();
-        }
+    private String mFilename;
+    private HashMap<String, String> mAttributes;
+    private boolean mHasThumbnail = false;
 
-        return sExifObj;
+    // Because the underlying implementation (jhead) uses static variables,
+    // there can only be one user at a time for the native functions (and
+    // they cannot keep state in the native code across function calls). We
+    // use sLock the serialize the accesses.
+    private static Object sLock = new Object();
+
+    /**
+     * Reads Exif tags from the specified JPEG file.
+     */
+    public ExifInterface(String filename) throws IOException {
+        mFilename = filename;
+        loadAttributes();
     }
 
     /**
-     * The following 3 static methods are handy routines for atomic operation
-     * of underlying jhead library. It retrieves EXIF data and then release
-     * ExifInterface immediately.
+     * Returns the value of the specified tag or {@code null} if there
+     * is no such tag in the file.
+     *
+     * @param tag the name of the tag.
      */
-    public static synchronized HashMap<String, String> loadExifData(String filename) {
-        ExifInterface exif = instance();
-        HashMap<String, String> exifData = null;
-        if (exif != null) {
-            exif.setFilename(filename);
-            exifData = exif.getAttributes();
-        }
-        return exifData;
-    }
-
-    public static synchronized void saveExifData(String filename, HashMap<String, String> exifData) {
-        ExifInterface exif = instance();
-        if (exif != null) {
-            exif.setFilename(filename);
-            exif.saveAttributes(exifData);
-        }
-    }
-
-    public static synchronized byte[] getExifThumbnail(String filename) {
-        ExifInterface exif = instance();
-        if (exif != null) {
-            exif.setFilename(filename);
-            return exif.getThumbnail();
-        }
-        return null;
-    }
-
-    public void setFilename(String filename) {
-        if (mFilename == null || !mFilename.equals(filename)) {
-            mFilename = filename;
-            mCachedAttributes = null;
-        }
+    public String getAttribute(String tag) {
+        return mAttributes.get(tag);
     }
 
     /**
-     * Given a HashMap of Exif tags and associated values, an Exif section in
-     * the JPG file is created and loaded with the tag data. saveAttributes()
-     * is expensive because it involves copying all the JPG data from one file
-     * to another and deleting the old file and renaming the other. It's best
-     * to collect all the attributes to write and make a single call rather
-     * than multiple calls for each attribute. You must call "commitChanges()"
-     * at some point to commit the changes.
+     * Set the value of the specified tag.
+     *
+     * @param tag the name of the tag.
+     * @param value the value of the tag.
      */
-    public void saveAttributes(HashMap<String, String> attributes) {
-        // format of string passed to native C code:
-        // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
-        // example:
-        // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
-        StringBuilder sb = new StringBuilder();
-        int size = attributes.size();
-        if (attributes.containsKey("hasThumbnail")) {
-            --size;
-        }
-        sb.append(size + " ");
-        for (Map.Entry<String, String> iter : attributes.entrySet()) {
-            String key = iter.getKey();
-            if (key.equals("hasThumbnail")) {
-                // this is a fake attribute not saved as an exif tag
-                continue;
-            }
-            String val = iter.getValue();
-            sb.append(key + "=");
-            sb.append(val.length() + " ");
-            sb.append(val);
-        }
-        String s = sb.toString();
-        saveAttributesNative(mFilename, s);
-        commitChangesNative(mFilename);
-        mSavedAttributes = true;
+    public void setAttribute(String tag, String value) {
+        mAttributes.put(tag, value);
     }
 
     /**
-     * Returns a HashMap loaded with the Exif attributes of the file. The key
-     * is the standard tag name and the value is the tag's value: e.g.
-     * Model -> Nikon. Numeric values are returned as strings.
+     * Initialize mAttributes with the attributes from the file mFilename.
+     *
+     * mAttributes is a HashMap which stores the Exif attributes of the file.
+     * The key is the standard tag name and the value is the tag's value: e.g.
+     * Model -> Nikon. Numeric values are stored as strings.
+     *
+     * This function also initialize mHasThumbnail to indicate whether the
+     * file has a thumbnail inside.
      */
-    public HashMap<String, String> getAttributes() {
-        if (mCachedAttributes != null) {
-            return mCachedAttributes;
-        }
+    private void loadAttributes() {
         // format of string passed from native C code:
         // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
         // example:
         // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
-        mCachedAttributes = new HashMap<String, String>();
+        mAttributes = new HashMap<String, String>();
 
-        String attrStr = getAttributesNative(mFilename);
+        String attrStr;
+        synchronized (sLock) {
+            attrStr = getAttributesNative(mFilename);
+        }
 
         // get count
         int ptr = attrStr.indexOf(' ');
@@ -215,17 +145,78 @@
             if (attrName.equals("hasThumbnail")) {
                 mHasThumbnail = attrValue.equalsIgnoreCase("true");
             } else {
-                mCachedAttributes.put(attrName, attrValue);
+                mAttributes.put(attrName, attrValue);
             }
         }
-        return mCachedAttributes;
     }
 
     /**
-     * Given a numerical white balance value, return a
-     * human-readable string describing it.
+     * Save the tag data into the JPEG file. This is expensive because it involves
+     * copying all the JPG data from one file to another and deleting the old file
+     * and renaming the other. It's best to use {@link #setAttribute(String,String)} to set all
+     * attributes to write and make a single call rather than multiple calls for
+     * each attribute.
      */
-    public static String whiteBalanceToString(int whitebalance) {
+    public void saveAttributes() throws IOException {
+        // format of string passed to native C code:
+        // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
+        // example:
+        // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
+        StringBuilder sb = new StringBuilder();
+        int size = mAttributes.size();
+        if (mAttributes.containsKey("hasThumbnail")) {
+            --size;
+        }
+        sb.append(size + " ");
+        for (Map.Entry<String, String> iter : mAttributes.entrySet()) {
+            String key = iter.getKey();
+            if (key.equals("hasThumbnail")) {
+                // this is a fake attribute not saved as an exif tag
+                continue;
+            }
+            String val = iter.getValue();
+            sb.append(key + "=");
+            sb.append(val.length() + " ");
+            sb.append(val);
+        }
+        String s = sb.toString();
+        synchronized (sLock) {
+            saveAttributesNative(mFilename, s);
+            commitChangesNative(mFilename);
+        }
+    }
+
+    /**
+     * Returns true if the JPEG file has a thumbnail.
+     */
+    public boolean hasThumbnail() {
+        return mHasThumbnail;
+    }
+
+    /**
+     * Returns the thumbnail inside the JPEG file, or {@code null} if there is no thumbnail.
+     */
+    public byte[] getThumbnail() {
+        synchronized (sLock) {
+            return getThumbnailNative(mFilename);
+        }
+    }
+
+    /**
+     * Returns a human-readable string describing the white balance value. Returns empty
+     * string if there is no white balance value or it is not recognized.
+     */
+    public String getWhiteBalanceString() {
+        String value = getAttribute(TAG_WHITE_BALANCE);
+        if (value == null) return "";
+
+        int whitebalance;
+        try {
+            whitebalance = Integer.parseInt(value);
+        } catch (NumberFormatException ex) {
+            return "";
+        }
+
         switch (whitebalance) {
             case WHITEBALANCE_AUTO:
                 return "Auto";
@@ -237,12 +228,21 @@
     }
 
     /**
-     * Given a numerical orientation, return a human-readable string describing
-     * the orientation.
+     * Returns a human-readable string describing the orientation value. Returns empty
+     * string if there is no orientation value or it it not recognized.
      */
-    public static String orientationToString(int orientation) {
-        // TODO: this function needs to be localized and use string resource ids
-        // rather than strings
+    public String getOrientationString() {
+        // TODO: this function needs to be localized.
+        String value = getAttribute(TAG_ORIENTATION);
+        if (value == null) return "";
+
+        int orientation;
+        try {
+            orientation = Integer.parseInt(value);
+        } catch (NumberFormatException ex) {
+            return "";
+        }
+
         String orientationString;
         switch (orientation) {
             case ORIENTATION_NORMAL:
@@ -277,48 +277,21 @@
     }
 
     /**
-     * Copies the thumbnail data out of the filename and puts it in the Exif
-     * data associated with the file used to create this object. You must call
-     * "commitChanges()" at some point to commit the changes.
+     * Returns the latitude and longitude value in a float array. The first element is
+     * the latitude, and the second element is the longitude.
      */
-    public boolean appendThumbnail(String thumbnailFileName) {
-        if (!mSavedAttributes) {
-            throw new RuntimeException("Must call saveAttributes "
-                    + "before calling appendThumbnail");
-        }
-        mHasThumbnail = appendThumbnailNative(mFilename, thumbnailFileName);
-        return mHasThumbnail;
-    }
-
-    public boolean hasThumbnail() {
-        if (!mSavedAttributes) {
-            getAttributes();
-        }
-        return mHasThumbnail;
-    }
-
-    public byte[] getThumbnail() {
-        return getThumbnailNative(mFilename);
-    }
-
-    public static float[] getLatLng(HashMap<String, String> exifData) {
-        if (exifData == null) {
-            return null;
-        }
-
-        String latValue = exifData.get(ExifInterface.TAG_GPS_LATITUDE);
-        String latRef = exifData.get(ExifInterface.TAG_GPS_LATITUDE_REF);
-        String lngValue = exifData.get(ExifInterface.TAG_GPS_LONGITUDE);
-        String lngRef = exifData.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
+    public float[] getLatLong() {
+        String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
+        String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
+        String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
+        String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
         float[] latlng = null;
 
         if (latValue != null && latRef != null
                 && lngValue != null && lngRef != null) {
             latlng = new float[2];
-            latlng[0] = ExifInterface.convertRationalLatLonToFloat(
-                    latValue, latRef);
-            latlng[1] = ExifInterface.convertRationalLatLonToFloat(
-                    lngValue, lngRef);
+            latlng[0] = convertRationalLatLonToFloat(latValue, latRef);
+            latlng[1] = convertRationalLatLonToFloat(lngValue, lngRef);
         }
 
         return latlng;
@@ -327,14 +300,12 @@
     private static SimpleDateFormat sFormatter =
             new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
 
-    // Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
-    // Returns -1 if the date time information if not available.
-    public static long getDateTime(HashMap<String, String> exifData) {
-        if (exifData == null) {
-            return -1;
-        }
-
-        String dateTimeString = exifData.get(ExifInterface.TAG_DATETIME);
+    /**
+     * Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
+     * Returns -1 if the date time information if not available.
+     */
+    public long getDateTime() {
+        String dateTimeString = mAttributes.get(TAG_DATETIME);
         if (dateTimeString == null) return -1;
 
         ParsePosition pos = new ParsePosition(0);
@@ -347,7 +318,7 @@
         }
     }
 
-    public static float convertRationalLatLonToFloat(
+    private static float convertRationalLatLonToFloat(
             String rationalString, String ref) {
         try {
             String [] parts = rationalString.split(",");
@@ -377,42 +348,6 @@
         }
     }
 
-    public static String convertRationalLatLonToDecimalString(
-            String rationalString, String ref, boolean usePositiveNegative) {
-            float result = convertRationalLatLonToFloat(rationalString, ref);
-
-            String preliminaryResult = String.valueOf(result);
-            if (usePositiveNegative) {
-                String neg = (ref.equals("S") || ref.equals("E")) ? "-" : "";
-                return neg + preliminaryResult;
-            } else {
-                return preliminaryResult + String.valueOf((char) 186) + " "
-                        + ref;
-            }
-    }
-
-    public static String makeLatLongString(double d) {
-        d = Math.abs(d);
-
-        int degrees = (int) d;
-
-        double remainder = d - degrees;
-        int minutes = (int) (remainder * 60D);
-        // really seconds * 1000
-        int seconds = (int) (((remainder * 60D) - minutes) * 60D * 1000D);
-
-        String retVal = degrees + "/1," + minutes + "/1," + seconds + "/1000";
-        return retVal;
-    }
-
-    public static String makeLatStringRef(double lat) {
-        return lat >= 0D ? "N" : "S";
-    }
-
-    public static String makeLonStringRef(double lon) {
-        return lon >= 0D ? "W" : "E";
-    }
-
     private native boolean appendThumbnailNative(String fileName,
             String thumbnailFileName);
 
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index f6d30e0..d9127e7 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -719,16 +719,20 @@
                 values.put(Audio.Media.IS_MUSIC, music);
                 values.put(Audio.Media.IS_PODCAST, podcasts);
             } else if (mFileType == MediaFile.FILE_TYPE_JPEG) {
-                HashMap<String, String> exifData =
-                        ExifInterface.loadExifData(entry.mPath);
-                if (exifData != null) {
-                    float[] latlng = ExifInterface.getLatLng(exifData);
+                ExifInterface exif = null;
+                try {
+                    exif = new ExifInterface(entry.mPath);
+                } catch (IOException ex) {
+                    // exif is null
+                }
+                if (exif != null) {
+                    float[] latlng = exif.getLatLong();
                     if (latlng != null) {
                         values.put(Images.Media.LATITUDE, latlng[0]);
                         values.put(Images.Media.LONGITUDE, latlng[1]);
                     }
 
-                    long time = ExifInterface.getDateTime(exifData);
+                    long time = exif.getDateTime();
                     if (time != -1) {
                         values.put(Images.Media.DATE_TAKEN, time);
                     }
diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
index a1c478f..4ed6869 100644
--- a/media/libstagefright/omx/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -65,6 +65,8 @@
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
     switch (mColorFormat) {
         case OMX_COLOR_FormatYUV420Planar:
             return renderYUV420Planar(data, size);
@@ -72,6 +74,9 @@
         case OMX_COLOR_FormatCbYCrY:
             return renderCbYCrY(data, size);
 
+        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+            return renderQCOMYUV420SemiPlanar(data, size);
+
         default:
         {
             LOGW("Cannot render color format %ld", mColorFormat);
@@ -242,6 +247,76 @@
     mIndex = 1 - mIndex;
 }
 
+void SoftwareRenderer::renderQCOMYUV420SemiPlanar(
+        const void *data, size_t size) {
+    if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+    }
+    CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
+
+    uint8_t *kAdjustedClip = initClip();
+
+    size_t offset = mIndex * mFrameSize;
+
+    void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+
+    uint32_t *dst_ptr = (uint32_t *)dst;
+
+    const uint8_t *src_y = (const uint8_t *)data;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight;
+
+    for (size_t y = 0; y < mDecodedHeight; ++y) {
+        for (size_t x = 0; x < mDecodedWidth; x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
+
+            signed u = (signed)src_u[x & ~1] - 128;
+            signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[b1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[r1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[b2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[r2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src_y += mDecodedWidth;
+
+        if (y & 1) {
+            src_u += mDecodedWidth;
+        }
+
+        dst_ptr += mDecodedWidth / 2;
+    }
+
+    mISurface->postBuffer(offset);
+    mIndex = 1 - mIndex;
+}
+
 uint8_t *SoftwareRenderer::initClip() {
     static const signed kClipMin = -278;
     static const signed kClipMax = 535;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index 69e93a1..10796f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -16,6 +16,7 @@
 
 package com.android.mediaframeworktest.stress;
 
+
 import com.android.mediaframeworktest.MediaFrameworkTest;
 
 import java.io.BufferedWriter;
@@ -26,6 +27,7 @@
 import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.os.Looper;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
@@ -54,7 +56,14 @@
     private static final String OUTPUT_FILE_EXT = ".3gp";
     private static final String MEDIA_STRESS_OUTPUT =
         "/sdcard/mediaStressOutput.txt";
-    
+    private Looper mCameraLooper = null;
+    private Looper mRecorderLooper = null;
+    private final Object lock = new Object();
+    private final Object recorderlock = new Object();
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000;  // Milliseconds.
+    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+    private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
+
     public MediaRecorderStressTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
     }
@@ -63,41 +72,129 @@
         getActivity();
         super.setUp();      
     }
-       
+
+    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+        public void onError(int error, android.hardware.Camera camera) {
+            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
+                assertTrue("Camera test mediaserver died", false);
+            }
+        }
+    }
+
+    private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
+        public void onError(MediaRecorder mr, int what, int extra) {
+            // fail the test case no matter what error come up
+            assertTrue("mediaRecorder error", false);
+        }
+    }
+
+    private void initializeCameraMessageLooper() {
+        Log.v(TAG, "start looper");
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by camera.
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                mCameraLooper = Looper.myLooper();
+                mCamera = Camera.open();
+                synchronized (lock) {
+                    lock.notify();
+                }
+                Looper.loop();
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+
+    private void initializeRecorderMessageLooper() {
+        Log.v(TAG, "start looper");
+        new Thread() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                mRecorderLooper = Looper.myLooper();
+                mRecorder = new MediaRecorder();
+                synchronized (recorderlock) {
+                    recorderlock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+
+    /*
+     * Terminates the message looper thread.
+     */
+    private void terminateCameraMessageLooper() {
+        mCameraLooper.quit();
+        try {
+            Thread.sleep(1000);
+        } catch (Exception e){
+            Log.v(TAG, e.toString());
+        }
+        mCamera.release();
+    }
+
+    /*
+     * Terminates the message looper thread.
+     */
+    private void terminateRecorderMessageLooper() {
+        mRecorderLooper.quit();
+        try {
+            Thread.sleep(1000);
+        } catch (Exception e){
+            Log.v(TAG, e.toString());
+        }
+        mRecorder.release();
+    }
+
     //Test case for stressing the camera preview.
     @LargeTest
     public void testStressCamera() throws Exception {
-        SurfaceHolder mSurfaceHolder;             
+        SurfaceHolder mSurfaceHolder;
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
         File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
         output.write("Camera start preview stress:\n");
-        output.write("Total number of loops:" + 
+        output.write("Total number of loops:" +
                 NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
-        try {        
+        try {
             Log.v(TAG, "Start preview");
             output.write("No of loop: ");
+
             for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++){
-                mCamera = Camera.open();
+                synchronized (lock) {
+                    initializeCameraMessageLooper();
+                    try {
+                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    } catch(Exception e) {
+                        Log.v(TAG, "wait was interrupted.");
+                    }
+                }
+                mCamera.setErrorCallback(mCameraErrorCallback);
                 mCamera.setPreviewDisplay(mSurfaceHolder);
                 mCamera.startPreview();
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
                 mCamera.stopPreview();
-                mCamera.release();
+                terminateCameraMessageLooper();
                 output.write(" ," + i);
             }
         } catch (Exception e) {
-                Log.v(TAG, e.toString());
+            assertTrue("CameraStressTest", false);
+            Log.v(TAG, e.toString());
         }
         output.write("\n\n");
         output.close();
     }
-    
+
     //Test case for stressing the camera preview.
     @LargeTest
     public void testStressRecorder() throws Exception {
         String filename;
-        SurfaceHolder mSurfaceHolder;             
+        SurfaceHolder mSurfaceHolder;
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
         File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
@@ -108,12 +205,20 @@
             output.write("No of loop: ");
             Log.v(TAG, "Start preview");
             for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++){
+                synchronized (recorderlock) {
+                    initializeRecorderMessageLooper();
+                    try {
+                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    } catch(Exception e) {
+                        Log.v(TAG, "wait was interrupted.");
+                    }
+                }
                 Log.v(TAG, "counter = " + i);
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
-                mRecorder = new MediaRecorder();
+                mRecorder.setOnErrorListener(mRecorderErrorCallback);
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
-                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                 mRecorder.setOutputFile(filename);
                 mRecorder.setVideoFrameRate(20);
                 mRecorder.setVideoSize(176,144);
@@ -125,47 +230,63 @@
                 Log.v(TAG, "prepare");
                 mRecorder.prepare();
                 Log.v(TAG, "before release");
-                Thread.sleep(WAIT_TIME_RECORDER_TEST);  
+                Thread.sleep(WAIT_TIME_RECORDER_TEST);
                 mRecorder.reset();
-                mRecorder.release();
+                terminateRecorderMessageLooper();
                 output.write(", " + i);
             }
         } catch (Exception e) {
-                Log.v(TAG, e.toString());
+            assertTrue("Recorder Stress test", false);
+            Log.v(TAG, e.toString());
         }
         output.write("\n\n");
         output.close();
     }
-    
-    
+
     //Stress test case for switching camera and video recorder preview.
     @LargeTest
     public void testStressCameraSwitchRecorder() throws Exception {
         String filename;
-        SurfaceHolder mSurfaceHolder;             
+        SurfaceHolder mSurfaceHolder;
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
         File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
         output.write("Camera and video recorder preview switching\n");
         output.write("Total number of loops:"
                 + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
-        try {    
+        try {
             Log.v(TAG, "Start preview");
             output.write("No of loop: ");
             for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++){
-                mCamera = Camera.open();
+                synchronized (lock) {
+                    initializeCameraMessageLooper();
+                    try {
+                        lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    } catch(Exception e) {
+                        Log.v(TAG, "wait was interrupted.");
+                    }
+                }
+                mCamera.setErrorCallback(mCameraErrorCallback);
                 mCamera.setPreviewDisplay(mSurfaceHolder);
                 mCamera.startPreview();
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
                 mCamera.stopPreview();
-                mCamera.release();
+                terminateCameraMessageLooper();
                 mCamera = null;
                 Log.v(TAG, "release camera");
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
-                mRecorder = new MediaRecorder();
+                synchronized (recorderlock) {
+                    initializeRecorderMessageLooper();
+                    try {
+                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    } catch(Exception e) {
+                        Log.v(TAG, "wait was interrupted.");
+                    }
+                }
+                mRecorder.setOnErrorListener(mRecorderErrorCallback);
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
-                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                 mRecorder.setOutputFile(filename);
                 mRecorder.setVideoFrameRate(20);
                 mRecorder.setVideoSize(176,144);
@@ -176,23 +297,24 @@
                 Log.v(TAG, "prepare");
                 mRecorder.prepare();
                 Log.v(TAG, "before release");
-                Thread.sleep(WAIT_TIME_CAMERA_TEST);  
-                mRecorder.release();
+                Thread.sleep(WAIT_TIME_CAMERA_TEST);
+                terminateRecorderMessageLooper();
                 Log.v(TAG, "release video recorder");
                 output.write(", " + i);
             }
         } catch (Exception e) {
+            assertTrue("Camer and recorder switch mode", false);
                 Log.v(TAG, e.toString());
         }
         output.write("\n\n");
         output.close();
     }
-    
+
     //Stress test case for record a video and play right away.
     @LargeTest
     public void testStressRecordVideoAndPlayback() throws Exception {
         String filename;
-        SurfaceHolder mSurfaceHolder;             
+        SurfaceHolder mSurfaceHolder;
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
         File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
@@ -204,10 +326,18 @@
             for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS; i++){
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
-                mRecorder = new MediaRecorder();
+                synchronized (recorderlock) {
+                    initializeRecorderMessageLooper();
+                    try {
+                        recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    } catch(Exception e) {
+                        Log.v(TAG, "wait was interrupted.");
+                    }
+                }
+                mRecorder.setOnErrorListener(mRecorderErrorCallback);
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
-                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);          
+                mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                 mRecorder.setOutputFile(filename);
                 mRecorder.setVideoFrameRate(20);
                 mRecorder.setVideoSize(352,288);
@@ -216,11 +346,11 @@
                 Log.v(TAG, "mediaRecorder setPreview");
                 mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
                 mRecorder.prepare();
-                mRecorder.start();               
+                mRecorder.start();
                 Thread.sleep(WAIT_TIME_RECORD);
                 Log.v(TAG, "Before stop");
                 mRecorder.stop();
-                mRecorder.release();
+                terminateRecorderMessageLooper();
                 //start the playback
                 MediaPlayer mp = new MediaPlayer();
                 mp.setDataSource(filename);
@@ -232,10 +362,10 @@
                 output.write(", " + i);
             }
         } catch (Exception e) {
+            assertTrue("record and playback", false);
                 Log.v(TAG, e.toString());
         }
         output.write("\n\n");
         output.close();
-    }   
+    }
 }
-
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 705794a..f969a46 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -33,11 +33,45 @@
 
 static void printGLString(const char *name, GLenum s)
 {
+     fprintf(stderr, "printGLString %s, %d\n", name, s);
      const char *v = (const char *)glGetString(s);
-     if (v)
-         printf("GL %s = %s\n", name, v);
+     int error = glGetError();
+     fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+         (unsigned int)v);
+     if ((v < (const char*) 0) || (v > (const char*) 0x1000))
+         fprintf(stderr, "GL %s = %s\n", name, v);
      else
-         printf("GL %s = (null)\n", name);
+         fprintf(stderr, "GL %s = (null)\n", name);
+}
+
+static const char* eglErrorToString[] = {
+    "EGL_SUCCESS",      // 0x3000 12288
+    "EGL_NOT_INITIALIZED",
+    "EGL_BAD_ACCESS",   // 0x3002 12290
+    "EGL_BAD_ALLOC",
+    "EGL_BAD_ATTRIBUTE",
+    "EGL_BAD_CONFIG",
+    "EGL_BAD_CONTEXT",  // 0x3006 12294
+    "EGL_BAD_CURRENT_SURFACE",
+    "EGL_BAD_DISPLAY",
+    "EGL_BAD_MATCH",
+    "EGL_BAD_NATIVE_PIXMAP",
+    "EGL_BAD_NATIVE_WINDOW",
+    "EGL_BAD_PARAMETER",  // 0x300c 12300
+    "EGL_BAD_SURFACE"
+};
+
+static void checkEglError(const char* op) {
+    for(EGLint error = eglGetError();
+		error != EGL_SUCCESS;
+	error = eglGetError()) {
+        const char* errorString = "unknown";
+        if (error >= EGL_SUCCESS && error <= EGL_BAD_SURFACE) {
+            errorString = eglErrorToString[error - EGL_SUCCESS];
+        }
+        fprintf(stderr, "%s() returned eglError %s (0x%x)\n", op,
+            errorString, error);
+    }
 }
 
 int main(int argc, char** argv)
@@ -63,19 +97,33 @@
      EGLNativeWindowType window = 0;
      window = android_createDisplaySurface();
 
+     checkEglError("<init>");
      dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     checkEglError("eglGetDisplay");
      eglInitialize(dpy, &majorVersion, &minorVersion);
+     checkEglError("eglInitialize");
+     fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
      EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &config);
-     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     fprintf(stderr, "Chosen config: 0x%08x\n", (unsigned long) config);
 
-    EGLint gl2_0Attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+     checkEglError("EGLUtils::selectConfigForNativeWindow");
+     surface = eglCreateWindowSurface(dpy, config, window, NULL);
+     checkEglError("eglCreateWindowSurface");
+
+     EGLint gl2_0Attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
 
      context = eglCreateContext(dpy, config, NULL, gl2_0Attribs);
+     checkEglError("eglCreateContext");
      eglMakeCurrent(dpy, surface, surface, context);
+     checkEglError("eglMakeCurrent");
      eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+     checkEglError("eglQuerySurface");
      eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+     checkEglError("eglQuerySurface");
      GLint dim = w<h ? w : h;
 
+     fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
      printGLString("Version", GL_VERSION);
      printGLString("Vendor", GL_VENDOR);
      printGLString("Renderer", GL_RENDERER);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 0e60dd6..c6be61d 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -649,11 +649,21 @@
         int N = packages.size();
         for (int a = N-1; a >= 0; a--) {
             PackageInfo pkg = packages.get(a);
-            ApplicationInfo app = pkg.applicationInfo;
-            if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                    || app.backupAgentName == null
-                    || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
-                            pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
+            try {
+                ApplicationInfo app = pkg.applicationInfo;
+                if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
+                        || app.backupAgentName == null
+                        || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                                pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
+                    packages.remove(a);
+                }
+                else {
+                    // we will need the shared library path, so look that up and store it here
+                    app = mPackageManager.getApplicationInfo(pkg.packageName,
+                            PackageManager.GET_SHARED_LIBRARY_FILES);
+                    pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles;
+                }
+            } catch (NameNotFoundException e) {
                 packages.remove(a);
             }
         }
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 30c25e0..60195b9 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
@@ -111,6 +112,30 @@
                 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
                 intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
                 mContext.sendStickyBroadcast(intent);
+
+                // Launch a dock activity
+                String category;
+                switch (mDockState) {
+                    case Intent.EXTRA_DOCK_STATE_CAR:
+                        category = Intent.CATEGORY_CAR_DOCK;
+                        break;
+                    case Intent.EXTRA_DOCK_STATE_DESK:
+                        category = Intent.CATEGORY_DESK_DOCK;
+                        break;
+                    default:
+                        category = null;
+                        break;
+                }
+                if (category != null) {
+                    intent = new Intent(Intent.ACTION_MAIN);
+                    intent.addCategory(category);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    try {
+                        mContext.startActivity(intent);
+                    } catch (ActivityNotFoundException e) {
+                        Log.w(TAG, e.getCause());
+                    }
+                }
             }
         }
     };
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 82cf1bc..45e0ceb 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3611,9 +3611,18 @@
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                PackageInstalledInfo res;
-                synchronized (mInstallLock) {
-                    res = installPackageLI(packageURI, flags, true, installerPackageName);
+                 // Result object to be returned
+                PackageInstalledInfo res = new PackageInstalledInfo();
+                res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+                res.uid = -1;
+                res.pkg = null;
+                res.removedInfo = new PackageRemovedInfo();
+                // Make a temporary copy of file from given packageURI
+                File tmpPackageFile = copyTempInstallFile(packageURI, res);
+                if (tmpPackageFile != null) {
+                    synchronized (mInstallLock) {
+                        installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
+                    }
                 }
                 if (observer != null) {
                     try {
@@ -3828,11 +3837,30 @@
             // Since we failed to install the new package we need to restore the old
             // package that we deleted.
             if(deletedPkg) {
+                File restoreFile = new File(deletedPackage.mPath);
+                if (restoreFile == null) {
+                    Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
+                    return;
+                }
+                File restoreTmpFile = createTempPackageFile();
+                if (restoreTmpFile == null) {
+                    Log.e(TAG, "Failed creating temp file when restoring pkg :  " + pkgName);
+                    return;
+                }
+                if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
+                    Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
+                    return;
+                }
+                PackageInstalledInfo restoreRes = new PackageInstalledInfo();
+                restoreRes.removedInfo = new PackageRemovedInfo();
                 installPackageLI(
-                        Uri.fromFile(new File(deletedPackage.mPath)),
+                        Uri.fromFile(restoreFile),
                         isForwardLocked(deletedPackage)
                         ? PackageManager.INSTALL_FORWARD_LOCK
-                                : 0, false, oldInstallerPackageName);
+                                : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
+                if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+                    Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
+                }
             }
         }
     }
@@ -3995,50 +4023,36 @@
         return new File(mAppInstallDir, publicZipFileName);
     }
 
-    private PackageInstalledInfo installPackageLI(Uri pPackageURI,
-            int pFlags, boolean newInstall, String installerPackageName) {
-        File tmpPackageFile = null;
-        String pkgName = null;
-        boolean forwardLocked = false;
-        boolean replacingExistingPackage = false;
-        // Result object to be returned
-        PackageInstalledInfo res = new PackageInstalledInfo();
-        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
-        res.uid = -1;
-        res.pkg = null;
-        res.removedInfo = new PackageRemovedInfo();
+    private File copyTempInstallFile(Uri pPackageURI,
+            PackageInstalledInfo res) {
+        File tmpPackageFile = createTempPackageFile();
+        int retCode = PackageManager.INSTALL_SUCCEEDED;
+        if (tmpPackageFile == null) {
+            res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            return null;
+        }
 
-        main_flow: try {
-            tmpPackageFile = createTempPackageFile();
-            if (tmpPackageFile == null) {
-                res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                break main_flow;
+        if (pPackageURI.getScheme().equals("file")) {
+            final File srcPackageFile = new File(pPackageURI.getPath());
+            // We copy the source package file to a temp file and then rename it to the
+            // destination file in order to eliminate a window where the package directory
+            // scanner notices the new package file but it's not completely copied yet.
+            if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
+                Log.e(TAG, "Couldn't copy package file to temp file.");
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
             }
-            tmpPackageFile.deleteOnExit();  // paranoia
-            if (pPackageURI.getScheme().equals("file")) {
-                final File srcPackageFile = new File(pPackageURI.getPath());
-                // We copy the source package file to a temp file and then rename it to the
-                // destination file in order to eliminate a window where the package directory
-                // scanner notices the new package file but it's not completely copied yet.
-                if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
-                    Log.e(TAG, "Couldn't copy package file to temp file.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
-            } else if (pPackageURI.getScheme().equals("content")) {
-                ParcelFileDescriptor fd;
-                try {
-                    fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
-                } catch (FileNotFoundException e) {
-                    Log.e(TAG, "Couldn't open file descriptor from download service.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
-                if (fd == null) {
-                    Log.e(TAG, "Couldn't open file descriptor from download service (null).");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
+        } else if (pPackageURI.getScheme().equals("content")) {
+            ParcelFileDescriptor fd = null;
+            try {
+                fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            }
+            if (fd == null) {
+                Log.e(TAG, "Couldn't open file descriptor from download service (null).");
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            } else {
                 if (Config.LOGV) {
                     Log.v(TAG, "Opened file descriptor from download service.");
                 }
@@ -4049,14 +4063,34 @@
                 // scanner notices the new package file but it's not completely copied yet.
                 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
                     Log.e(TAG, "Couldn't copy package stream to temp file.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
+                    retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                 }
-            } else {
-                Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
-                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
-                break main_flow;
             }
+        } else {
+            Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
+            retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
+        }
+
+        res.returnCode = retCode;
+        if (retCode != PackageManager.INSTALL_SUCCEEDED) {
+            if (tmpPackageFile != null && tmpPackageFile.exists()) {
+                tmpPackageFile.delete();
+            }
+            return null;
+        }
+        return tmpPackageFile;
+    }
+
+    private void installPackageLI(Uri pPackageURI,
+            int pFlags, boolean newInstall, String installerPackageName,
+            File tmpPackageFile, PackageInstalledInfo res) {
+        String pkgName = null;
+        boolean forwardLocked = false;
+        boolean replacingExistingPackage = false;
+        // Result object to be returned
+        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+
+        main_flow: try {
             pkgName = PackageParser.parsePackageName(
                     tmpPackageFile.getAbsolutePath(), 0);
             if (pkgName == null) {
@@ -4128,7 +4162,6 @@
                 tmpPackageFile.delete();
             }
         }
-        return res;
     }
     
     private int setPermissionsLI(String pkgName,
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 53ff78e..63bef54 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -665,6 +665,15 @@
                 }
             }
         }
+
+        for (WifiConfiguration.EnterpriseField field :
+                config.enterpriseFields) {
+            value = WifiNative.getNetworkVariableCommand(netId,
+                    field.varName());
+            if (!TextUtils.isEmpty(value)) {
+                field.setValue(value);
+            }
+        }
     }
 
     /**
@@ -877,103 +886,20 @@
                 break setVariables;
             }
 
-            if ((config.eap != null) && !WifiNative.setNetworkVariableCommand(
+            for (WifiConfiguration.EnterpriseField field
+                    : config.enterpriseFields) {
+                String varName = field.varName();
+                String value = field.value();
+                if ((value != null) && !WifiNative.setNetworkVariableCommand(
                     netId,
-                    WifiConfiguration.eapVarName,
-                    config.eap)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set eap: "+
-                          config.eap);
+                    varName,
+                    value)) {
+                    if (DBG) {
+                        Log.d(TAG, config.SSID + ": failed to set " + varName +
+                              ": " + value);
+                    }
+                    break setVariables;
                 }
-                break setVariables;
-            }
-
-            if ((config.phase2 != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.phase2VarName,
-                    config.phase2)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set phase2: "+
-                          config.phase2);
-                }
-                break setVariables;
-            }
-
-            if ((config.identity != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.identityVarName,
-                    config.identity)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set identity: "+
-                          config.identity);
-                }
-                break setVariables;
-            }
-
-            if ((config.anonymousIdentity != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.anonymousIdentityVarName,
-                    config.anonymousIdentity)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set anonymousIdentity: "+
-                          config.anonymousIdentity);
-                }
-                break setVariables;
-            }
-
-            if ((config.password != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.passwordVarName,
-                    config.password)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set password: "+
-                          config.password);
-                }
-                break setVariables;
-            }
-
-            if ((config.clientCert != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.clientCertVarName,
-                    config.clientCert)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set clientCert: "+
-                          config.clientCert);
-                }
-                break setVariables;
-            }
-
-            if ((config.caCert != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.caCertVarName,
-                    config.caCert)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set caCert: "+
-                          config.caCert);
-                }
-                break setVariables;
-            }
-
-            if ((config.privateKey != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.privateKeyVarName,
-                    config.privateKey)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set privateKey: "+
-                          config.privateKey);
-                }
-                break setVariables;
-            }
-
-            if ((config.privateKeyPasswd != null) && !WifiNative.setNetworkVariableCommand(
-                    netId,
-                    WifiConfiguration.privateKeyPasswdVarName,
-                    config.privateKeyPasswd)) {
-                if (DBG) {
-                    Log.d(TAG, config.SSID + ": failed to set privateKeyPasswd: "+
-                          config.privateKeyPasswd);
-                }
-                break setVariables;
             }
 
             return netId;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index bd2c3ed..d53f002 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -442,6 +442,8 @@
     // Who is holding the screen on.
     Session mHoldingScreenOn;
 
+    boolean mTurnOnScreen;
+    
     /**
      * Whether the UI is currently running in touch mode (not showing
      * navigational focus because the user is directly pressing the screen).
@@ -2208,6 +2210,10 @@
                         && !win.mCommitDrawPending && !mDisplayFrozen) {
                     applyEnterAnimationLocked(win);
                 }
+                if (displayed && (win.mAttrs.flags
+                        & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+                    win.mTurnOnScreen = true;
+                }
                 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
                     // To change the format, we need to re-build the surface.
                     win.destroySurfaceLocked();
@@ -6479,6 +6485,7 @@
         int mLastLayer;
         boolean mHaveFrame;
         boolean mObscured;
+        boolean mTurnOnScreen;
 
         WindowState mNextOutsideTouch;
 
@@ -7049,7 +7056,7 @@
                         + " attHidden=" + mAttachedHidden
                         + " tok.hiddenRequested="
                         + (mAppToken != null ? mAppToken.hiddenRequested : false)
-                        + " tok.idden="
+                        + " tok.hidden="
                         + (mAppToken != null ? mAppToken.hidden : false)
                         + " animating=" + mAnimating
                         + " tok animating="
@@ -7078,10 +7085,20 @@
                 if (mAttrs.type != TYPE_APPLICATION_STARTING
                         && mAppToken != null) {
                     mAppToken.firstWindowDrawn = true;
-                    if (mAnimation == null && mAppToken.startingData != null) {
+                    
+                    if (mAppToken.startingData != null) {
                         if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
                                 + mToken
                                 + ": first real window is shown, no animation");
+                        // If this initial window is animating, stop it -- we
+                        // will do an animation to reveal it from behind the
+                        // starting window, so there is no need for it to also
+                        // be doing its own stuff.
+                        if (mAnimation != null) {
+                            mAnimation = null;
+                            // Make sure we clean up the animation.
+                            mAnimating = true;
+                        }
                         mFinishedStarting.add(mAppToken);
                         mH.sendEmptyMessage(H.FINISHED_STARTING);
                     }
@@ -7710,10 +7727,11 @@
                         pw.print(" mDestroying="); pw.print(mDestroying);
                         pw.print(" mRemoved="); pw.println(mRemoved);
             }
-            if (mOrientationChanging || mAppFreezing) {
+            if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
                 pw.print(prefix); pw.print("mOrientationChanging=");
                         pw.print(mOrientationChanging);
-                        pw.print(" mAppFreezing="); pw.println(mAppFreezing);
+                        pw.print(" mAppFreezing="); pw.print(mAppFreezing);
+                        pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
             }
             if (mHScale != 1 || mVScale != 1) {
                 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
@@ -9782,6 +9800,12 @@
             Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
             mH.sendMessage(m);
         }
+        
+        if (mTurnOnScreen) {
+            mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
+                    LocalPowerManager.BUTTON_EVENT, true);
+            mTurnOnScreen = false;
+        }
     }
 
     void requestAnimationLocked(long delay) {
@@ -9803,6 +9827,10 @@
         try {
             if (win.mSurface != null) {
                 win.mSurface.show();
+                if (win.mTurnOnScreen) {
+                    win.mTurnOnScreen = false;
+                    mTurnOnScreen = true;
+                }
             }
             return true;
         } catch (RuntimeException e) {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 4368464..2672c6d 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -129,6 +129,8 @@
             return uri.getSchemeSpecificPart();
         }
 
+        // TODO: We don't check for SecurityException here (requires
+        // READ_PHONE_STATE permission).
         if (scheme.equals("voicemail")) {
             return TelephonyManager.getDefault().getVoiceMailNumber();
         }
@@ -1179,6 +1181,35 @@
     }
 
     /**
+     * isVoiceMailNumber: checks a given number against the voicemail
+     *   number provided by the RIL and SIM card. The caller must have
+     *   the READ_PHONE_STATE credential.
+     *
+     * @param number the number to look up.
+     * @return true if the number is in the list of voicemail. False
+     * otherwise, including if the caller does not have the permission
+     * to read the VM number.
+     * @hide TODO: pending API Council approval
+     */
+    public static boolean isVoiceMailNumber(String number) {
+        String vmNumber;
+
+        try {
+            vmNumber = TelephonyManager.getDefault().getVoiceMailNumber();
+        } catch (SecurityException ex) {
+            return false;
+        }
+
+        // Strip the separators from the number before comparing it
+        // to the list.
+        number = extractNetworkPortion(number);
+
+        // compare tolerates null so we need to make sure that we
+        // don't return true when both are null.
+        return !TextUtils.isEmpty(number) && compare(number, vmNumber);
+    }
+
+    /**
      * Translates any alphabetic letters (i.e. [A-Za-z]) in the
      * specified phone number into the equivalent numeric digits,
      * according to the phone keypad letter mapping described in
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index c8490e9..01b1746 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -101,13 +101,12 @@
     public boolean isCachedPhotoCurrent;
 
     private boolean mIsEmergency;
-
-    // Don't keep checking VM if it's going to throw an exception for this proc.
-    private static boolean sSkipVmCheck = false;
+    private boolean mIsVoiceMail;
 
     public CallerInfo() {
         // TODO: Move all the basic initialization here?
         mIsEmergency = false;
+        mIsVoiceMail = false;
     }
 
     /**
@@ -220,32 +219,15 @@
     public static CallerInfo getCallerInfo(Context context, String number) {
         if (TextUtils.isEmpty(number)) {
             return null;
-        } else {
-            // Change the callerInfo number ONLY if it is an emergency number
-            // or if it is the voicemail number.  If it is either, take a
-            // shortcut and skip the query.
-            if (PhoneNumberUtils.isEmergencyNumber(number)) {
-                return new CallerInfo().markAsEmergency(context);
-            } else {
-                try {
-                    if (!sSkipVmCheck && PhoneNumberUtils.compare(number,
-                                TelephonyManager.getDefault().getVoiceMailNumber())) {
-                        CallerInfo ci = new CallerInfo();
+        }
 
-                        // Note we're setting the phone number here (refer to javadoc
-                        // comments at the top of CallerInfo class).
-                        ci.phoneNumber = TelephonyManager.getDefault().getVoiceMailAlphaTag();
-                        // TODO: FIND ANOTHER ICON
-                        //info.photoResource = android.R.drawable.badge_voicemail;
-                        return ci;
-                    }
-                } catch (SecurityException ex) {
-                    // Don't crash if this process doesn't have permission to
-                    // retrieve VM number.  It's still allowed to look up caller info.
-                    // But don't try it again.
-                    sSkipVmCheck = true;
-                }
-            }
+        // Change the callerInfo number ONLY if it is an emergency number
+        // or if it is the voicemail number.  If it is either, take a
+        // shortcut and skip the query.
+        if (PhoneNumberUtils.isEmergencyNumber(number)) {
+            return new CallerInfo().markAsEmergency(context);
+        } else if (PhoneNumberUtils.isVoiceMailNumber(number)) {
+            return new CallerInfo().markAsVoiceMail();
         }
 
         Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
@@ -304,6 +286,13 @@
     }
 
     /**
+     * @return true if the caller info is a voicemail number.
+     */
+    public boolean isVoiceMailNumber() {
+        return mIsVoiceMail;
+    }
+
+    /**
      * Mark this CallerInfo as an emergency call.
      * @param context To lookup the localized 'Emergency Number' string.
      * @return this instance.
@@ -323,6 +312,37 @@
         return this;
     }
 
+
+    /**
+     * Mark this CallerInfo as a voicemail call. The voicemail label
+     * is obtained from the telephony manager. Caller must hold the
+     * READ_PHONE_STATE permission otherwise the phoneNumber will be
+     * set to null.
+     * @return this instance.
+     */
+    // TODO: As in the emergency number handling, we end up writing a
+    // string in the phone number field.
+    /* package */ CallerInfo markAsVoiceMail() {
+        mIsVoiceMail = true;
+
+        try {
+            String voiceMailLabel = TelephonyManager.getDefault().getVoiceMailAlphaTag();
+
+            phoneNumber = voiceMailLabel;
+        } catch (SecurityException se) {
+            // Should never happen: if this process does not have
+            // permission to retrieve VM tag, it should not have
+            // permission to retrieve VM number and would not call
+            // this method.
+            // Leave phoneNumber untouched.
+            Log.e(TAG, "Cannot access VoiceMail.", se);
+        }
+        // TODO: There is no voicemail picture?
+        // FIXME: FIND ANOTHER ICON
+        // photoResource = android.R.drawable.badge_voicemail;
+        return this;
+    }
+
     private static String normalize(String s) {
         if (s == null || s.length() > 0) {
             return s;
@@ -330,4 +350,31 @@
             return null;
         }
     }
+
+    /**
+     * @return a string debug representation of this instance.
+     */
+    public String toString() {
+        return new StringBuilder(384)
+                .append("\nname: " + name)
+                .append("\nphoneNumber: " + phoneNumber)
+                .append("\ncnapName: " + cnapName)
+                .append("\nnumberPresentation: " + numberPresentation)
+                .append("\nnamePresentation: " + namePresentation)
+                .append("\ncontactExits: " + contactExists)
+                .append("\nphoneLabel: " + phoneLabel)
+                .append("\nnumberType: " + numberType)
+                .append("\nnumberLabel: " + numberLabel)
+                .append("\nphotoResource: " + photoResource)
+                .append("\nperson_id: " + person_id)
+                .append("\nneedUpdate: " + needUpdate)
+                .append("\ncontactRefUri: " + contactRefUri)
+                .append("\ncontactRingtoneUri: " + contactRefUri)
+                .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail)
+                .append("\ncachedPhoto: " + cachedPhoto)
+                .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
+                .append("\nemergency: " + mIsEmergency)
+                .append("\nvoicemail " + mIsVoiceMail)
+                .toString();
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 4227a84..802e79b 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -47,9 +47,6 @@
 
     private CallerInfoAsyncQueryHandler mHandler;
 
-    // Don't keep checking VM if it's going to throw an exception for this proc.
-    private static boolean sSkipVmCheck = false;
-
     /**
      * Interface for a CallerInfoAsyncQueryHandler result return.
      */
@@ -227,18 +224,7 @@
                     // comments at the top of CallerInfo class).
                     mCallerInfo = new CallerInfo().markAsEmergency(mQueryContext);
                 } else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
-                    mCallerInfo = new CallerInfo();
-                    try {
-                        // Note we're setting the phone number here (refer to javadoc
-                        // comments at the top of CallerInfo class).
-                        mCallerInfo.phoneNumber =
-                                TelephonyManager.getDefault().getVoiceMailAlphaTag();
-                    } catch (SecurityException ex) {
-                        // Should never happen: if this process does not have
-                        // permission to retrieve VM tag, it should not have
-                        // permission to retrieve VM number and would not generate
-                        // an EVENT_VOICEMAIL_NUMBER.  But if it happens, don't crash.
-                    }
+                    mCallerInfo = new CallerInfo().markAsVoiceMail();
                 } else {
                     mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor);
                     // Use the number entered by the user for display.
@@ -258,7 +244,7 @@
             //notify the listener that the query is complete.
             if (cw.listener != null) {
                 if (DBG) log("notifying listener: " + cw.listener.getClass().toString() +
-                        " for token: " + token);
+                             " for token: " + token + mCallerInfo);
                 cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
             }
         }
@@ -315,23 +301,10 @@
         // check to see if these are recognized numbers, and use shortcuts if we can.
         if (PhoneNumberUtils.isEmergencyNumber(number)) {
             cw.event = EVENT_EMERGENCY_NUMBER;
+        } else if (PhoneNumberUtils.isVoiceMailNumber(number)) {
+            cw.event = EVENT_VOICEMAIL_NUMBER;
         } else {
-            String vmNumber = null;
-            if (!sSkipVmCheck){
-                try {
-                    vmNumber = TelephonyManager.getDefault().getVoiceMailNumber();
-                } catch (SecurityException ex) {
-                    // Don't crash if this process doesn't have permission to
-                    // retrieve VM number.  It's still allowed to look up caller info.
-                    // But don't try it again.
-                    sSkipVmCheck = true;
-                }
-            }
-            if (PhoneNumberUtils.compare(number, vmNumber)) {
-                cw.event = EVENT_VOICEMAIL_NUMBER;
-            } else {
-                cw.event = EVENT_NEW_QUERY;
-            }
+            cw.event = EVENT_NEW_QUERY;
         }
 
         c.mHandler.startQuery (token, cw, contactRef, null, null, null, null);
diff --git a/telephony/tests/TelephonyTest/AndroidManifest.xml b/telephony/tests/TelephonyTest/AndroidManifest.xml
index c0cc0d5..b2a481b 100644
--- a/telephony/tests/TelephonyTest/AndroidManifest.xml
+++ b/telephony/tests/TelephonyTest/AndroidManifest.xml
@@ -28,8 +28,9 @@
             </intent-filter>
         </activity>
     </application>
-     <instrumentation android:name=".TelephonyUnitTestRunner"
-         android:targetPackage="com.android.telephonytest"
-         android:label="Telephony unit tests InstrumentationRunner">
-     </instrumentation>
+    <instrumentation android:name=".TelephonyUnitTestRunner"
+        android:targetPackage="com.android.telephonytest"
+        android:label="Telephony unit tests InstrumentationRunner">
+    </instrumentation>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 </manifest>
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
index 5da940d..9e1af31 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
@@ -37,6 +37,7 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(com.android.telephonytest.unit.CallerInfoUnitTest.class);
+        suite.addTestSuite(com.android.telephonytest.unit.PhoneNumberUtilsUnitTest.class);
         return suite;
     }
 
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
index 4cd0266..0f24f15 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
@@ -107,6 +107,16 @@
         assertIsValidEmergencyCallerInfo();
     }
 
+    // TODO: Add more tests:
+    /**
+     * Check if the voice mail number cannot be retrieved that the
+     * original phone number is preserved.
+     */
+    /**
+     * Check the markAs* methods work.
+     */
+
+
     //
     // Helpers
     //
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
new file mode 100644
index 0000000..2d3c548
--- /dev/null
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.telephonytest.unit;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+
+/*
+ * Check the PhoneNumberUtils utility class works as expected.
+ *
+ */
+
+public class PhoneNumberUtilsUnitTest extends AndroidTestCase {
+    private String mVoiceMailNumber;
+    private static final String TAG = "PhoneNumberUtilsUnitTest";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // FIXME: Why are we getting a security exception here? The
+        // permission is declared in the manifest....
+        // mVoiceMailNumber = TelephonyManager.getDefault().getVoiceMailNumber();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Basic checks for the VoiceMail number.
+     * Assumes READ_PHONE_STATE permission and we don't have it.
+     */
+    // TODO: Figure out why we don't have the permission declared in the manifest.
+    @SmallTest
+    public void testWithNumberNotEqualToVoiceMail() throws Exception {
+        assertFalse(PhoneNumberUtils.isVoiceMailNumber("911"));
+        assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911"));
+        assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567"));
+        assertFalse(PhoneNumberUtils.isVoiceMailNumber(""));
+        assertFalse(PhoneNumberUtils.isVoiceMailNumber(null));
+        // FIXME:
+        // assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber));
+    }
+
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
index c62f94f..f2025c6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
@@ -36,8 +36,11 @@
     public void testHandlerThread() throws Exception {
         HandlerThread th1 =  new HandlerThread("HandlerThreadTest") {
             protected void onLooperPrepared() {
-                mDidSetup = true;
-                mLooperTid = Process.myTid();
+                synchronized (HandlerThreadTest.this) {
+                    mDidSetup = true;
+                    mLooperTid = Process.myTid();
+                    HandlerThreadTest.this.notify();
+                }
             }
         };
         
@@ -49,14 +52,23 @@
         assertTrue(th1.isAlive());
         assertNotNull(th1.getLooper());
        
-        /* 
-         * Since getLooper() will block until the HandlerThread is setup, we are guaranteed
-         * that mDidSetup and mLooperTid will have been initalized. If they have not, then 
-         * this test should fail
-         */
+        // The call to getLooper() internally blocks until the looper is
+        // available, but will call onLooperPrepared() after that.  So we
+        // need to block here to wait for our onLooperPrepared() to complete
+        // and fill in the values we expect.
+        synchronized (this) {
+            while (!mDidSetup) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+        
+        // Make sure that the process was set.
+        assertNotSame(-1, mLooperTid);
         // Make sure that the onLooperPrepared() was called on a different thread.
         assertNotSame(Process.myTid(), mLooperTid);
-        assertTrue(mDidSetup);
         
         final Handler h1 = new Handler(th1.getLooper()) {
             public void handleMessage(Message msg) {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 8fea967..395e572 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -96,7 +96,9 @@
         // Android layout tests are stored in "layout_tests". The following two
         // tests expect "LayoutTests" in their output.
         "storage/domstorage/localstorage/iframe-events.html",
-        "storage/domstorage/sessionstorage/iframe-events.html"
+        "storage/domstorage/sessionstorage/iframe-events.html",
+        // below tests (failed or crashes) are filtered out temporarily due to prioritizing
+        "editing/selection/move-left-right.html",
     };
     
     static void fillIgnoreResultSet() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index cc2f1f5..85e0422 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -1,5 +1,23 @@
+/*
+ * 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.dumprendertree;
 
+import com.android.dumprendertree.forwarder.ForwardService;
+
 import android.util.Log;
 
 import java.io.BufferedOutputStream;
@@ -12,6 +30,12 @@
 public class FsUtils {
 
     private static final String LOGTAG = "FsUtils";
+    static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
+    static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
+    static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
+    static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
+    static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
+
     private FsUtils() {
         //no creation of instances
     }
@@ -77,4 +101,24 @@
         return status;
     }
 
+    public static String getTestUrl(String path) {
+        String url = null;
+        if (!path.startsWith(HTTP_TESTS_PREFIX)) {
+            url = "file://" + path;
+        } else {
+            ForwardService.getForwardService().startForwardService();
+            if (path.startsWith(HTTPS_TESTS_PREFIX)) {
+                // still cut the URL after "http/tests/"
+                url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
+            } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
+                    && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
+                    && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
+                url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
+            } else {
+                url = "file://" + path;
+            }
+        }
+        return url;
+    }
+
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index e4c8716..235e10e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -19,6 +19,7 @@
 import com.android.dumprendertree.TestShellActivity.DumpDataType;
 import com.android.dumprendertree.forwarder.AdbUtils;
 import com.android.dumprendertree.forwarder.ForwardServer;
+import com.android.dumprendertree.forwarder.ForwardService;
 
 import android.app.Instrumentation;
 import android.content.Intent;
@@ -143,17 +144,6 @@
     static final String LAYOUT_RESULTS_CRASHED_RESULT_FILE = "results/layout_tests_crashed.txt";
     static final String LAYOUT_TESTS_RUNNER = "run_layout_tests.py";
 
-    static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
-    static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
-    static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
-    static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
-    static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
-
-
-    static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com";
-    static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt";
-    private ForwardServer fs8000, fs8080, fs8443;
-
     private MyTestRecorder mResultRecorder;
     private Vector<String> mTestList;
     private boolean mRebaselineResults;
@@ -162,45 +152,6 @@
 
     public LayoutTestsAutoTest() {
       super("com.android.dumprendertree", TestShellActivity.class);
-
-      int addr = getForwardHostAddr();
-      if(addr != -1) {
-          fs8000 = new ForwardServer(8000, addr, 8000);
-          fs8080 = new ForwardServer(8080, addr, 8080);
-          fs8443 = new ForwardServer(8443, addr, 8443);
-      }
-    }
-
-    private int getForwardHostAddr() {
-        int addr = -1;
-        String host = null;
-        File forwardHostConf = new File(FORWARD_HOST_CONF);
-        if (forwardHostConf.isFile()) {
-            BufferedReader hostReader = null;
-            try {
-                hostReader = new BufferedReader(new FileReader(forwardHostConf));
-                host = hostReader.readLine();
-                Log.v(LOGTAG, "read forward host from file: " + host);
-            } catch (IOException ioe) {
-                Log.v(LOGTAG, "cannot read forward host from file", ioe);
-            } finally {
-                if (hostReader != null) {
-                    try {
-                        hostReader.close();
-                    } catch (IOException ioe) {
-                        // burn!!!
-                    }
-                }
-            }
-        }
-        if (host == null || host.length() == 0)
-            host = DEFAULT_TEST_HOST;
-        try {
-            addr = AdbUtils.resolve(host);
-        } catch (IOException ioe) {
-            Log.e(LOGTAG, "failed to resolve server address", ioe);
-        }
-        return addr;
     }
 
     // This function writes the result of the layout test to
@@ -366,7 +317,7 @@
         Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.setClass(activity, TestShellActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
-        intent.putExtra(TestShellActivity.TEST_URL, getTestUrl(test));
+        intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(test));
         intent.putExtra(TestShellActivity.RESULT_FILE, resultFile);
         intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
         activity.startActivity(intent);
@@ -450,49 +401,10 @@
         }
 
         FsUtils.updateTestStatus(TEST_STATUS_FILE, "#DONE");
-        if(fs8000 != null)
-            fs8000.stop();
-        if(fs8080 != null)
-            fs8080.stop();
-        if(fs8443 != null)
-            fs8443.stop();
-
+        ForwardService.getForwardService().stopForwardService();
         activity.finish();
     }
 
-    private void startForwardServerIfNeeded() {
-        try {
-            if(fs8000 != null)
-                fs8000.start();
-            if(fs8080 != null)
-                fs8080.start();
-            if(fs8443 != null)
-                fs8443.start();
-        } catch (IOException ioe) {
-            Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe);
-        }
-    }
-
-    private String getTestUrl(String path) {
-        String url = null;
-        if (!path.startsWith(HTTP_TESTS_PREFIX)) {
-            url = "file://" + path;
-        } else {
-            startForwardServerIfNeeded();
-            if (path.startsWith(HTTPS_TESTS_PREFIX)) {
-                // still cut the URL after "http/tests/"
-                url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
-            } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
-                    && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
-                    && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
-                url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
-            } else {
-                url = "file://" + path;
-            }
-        }
-        return url;
-    }
-
     private String getTestPath() {
         LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index 71d9758..50b7c3f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree;
 
 import android.app.Activity;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index 995c129..fbce78a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree;
 
 import android.app.Activity;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 663df83..074d90f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.dumprendertree;
 
+import com.android.dumprendertree.forwarder.ForwardService;
+
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
@@ -184,6 +186,7 @@
         } catch (IOException ioe) {
             Log.w(LOGTAG, "Failed to close test list file.", ioe);
         }
+        ForwardService.getForwardService().stopForwardService();
         finished();
     }
 
@@ -215,10 +218,9 @@
             builder.create().show();
             return;
         }
-        url = "file://" + url;
         Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
-        intent.putExtra(TestShellActivity.TEST_URL, url);
+        intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(url));
         intent.putExtra(TIMEOUT_IN_MILLIS, 10000);
         executeIntent(intent);
     }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
index 9a3e9c2..c2ecf3a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
 
 import android.util.Log;
@@ -44,7 +60,6 @@
         DataInputStream dis = new DataInputStream(localSocket.getInputStream());
         OutputStream os = localSocket.getOutputStream();
         int count_read = 0;
-        byte[] buf = new byte[128];
 
         if (localSocket == null || dis == null || os == null)
             return -1;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
index 74e018e..14f8fbe 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
 
 import android.util.Log;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
new file mode 100644
index 0000000..8b7de6e
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
@@ -0,0 +1,115 @@
+/*
+ * 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.dumprendertree.forwarder;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import android.util.Log;
+
+public class ForwardService {
+
+    private ForwardServer fs8000, fs8080, fs8443;
+
+    private static ForwardService inst;
+
+    private static final String LOGTAG = "ForwardService";
+
+    private static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com";
+
+    private static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt";
+
+    private ForwardService() {
+        int addr = getForwardHostAddr();
+        if (addr != -1) {
+            fs8000 = new ForwardServer(8000, addr, 8000);
+            fs8080 = new ForwardServer(8080, addr, 8080);
+            fs8443 = new ForwardServer(8443, addr, 8443);
+        }
+    }
+
+    public static ForwardService getForwardService() {
+        if (inst == null) {
+            inst = new ForwardService();
+        }
+        return inst;
+    }
+
+    public void startForwardService() {
+        try {
+            if (fs8000 != null)
+                fs8000.start();
+            if (fs8080 != null)
+                fs8080.start();
+            if (fs8443 != null)
+                fs8443.start();
+        } catch (IOException ioe) {
+            Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe);
+            return;
+        }
+    }
+
+    public void stopForwardService() {
+        if (fs8000 != null) {
+            fs8000.stop();
+            fs8000 = null;
+        }
+        if (fs8080 != null) {
+            fs8080.stop();
+            fs8080 = null;
+        }
+        if (fs8443 != null) {
+            fs8443.stop();
+            fs8443 = null;
+        }
+        Log.v(LOGTAG, "forwarders stopped.");
+    }
+
+    private static int getForwardHostAddr() {
+        int addr = -1;
+        String host = null;
+        File forwardHostConf = new File(FORWARD_HOST_CONF);
+        if (forwardHostConf.isFile()) {
+            BufferedReader hostReader = null;
+            try {
+                hostReader = new BufferedReader(new FileReader(forwardHostConf));
+                host = hostReader.readLine();
+                Log.v(LOGTAG, "read forward host from file: " + host);
+            } catch (IOException ioe) {
+                Log.v(LOGTAG, "cannot read forward host from file", ioe);
+            } finally {
+                if (hostReader != null) {
+                    try {
+                        hostReader.close();
+                    } catch (IOException ioe) {
+                        // burn!!!
+                    }
+                }
+            }
+        }
+        if (host == null || host.length() == 0)
+            host = DEFAULT_TEST_HOST;
+        try {
+            addr = AdbUtils.resolve(host);
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "failed to resolve server address", ioe);
+        }
+        return addr;
+    }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
index e1e04a7..a1f3cdf 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
 
 import android.util.Log;
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
index dc959f5..aea124b 100644
--- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -29,7 +29,6 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Set;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -145,7 +144,7 @@
                 public Cursor query(Uri uri, String[] projection, String selection,
                         String[] selectionArgs, String sortOrder) {
                     // Return cursor over specific set of values
-                    return getCursor(sTestValues1);
+                    return getCursor(sTestValues1, 1);
                 }
             }, null, 0);
         } catch (OperationApplicationException e) {
@@ -153,11 +152,62 @@
         }
     }
 
+    public void testAssertNoValues() {
+        // Build an operation to assert values match provider
+        ContentProviderOperation op1 = ContentProviderOperation.newAssertQuery(sTestUri1)
+                .withExpectedCount(1).build();
+
+        try {
+            // Assert that values match from cursor
+            ContentProviderResult result = op1.apply(new TestContentProvider() {
+                public Cursor query(Uri uri, String[] projection, String selection,
+                        String[] selectionArgs, String sortOrder) {
+                    // Return cursor over specific set of values
+                    return getCursor(sTestValues1, 1);
+                }
+            }, null, 0);
+        } catch (OperationApplicationException e) {
+            fail("newAssert() failed");
+        }
+
+        ContentProviderOperation op2 = ContentProviderOperation.newAssertQuery(sTestUri1)
+                .withExpectedCount(0).build();
+
+        try {
+            // Assert that values match from cursor
+            ContentProviderResult result = op2.apply(new TestContentProvider() {
+                public Cursor query(Uri uri, String[] projection, String selection,
+                        String[] selectionArgs, String sortOrder) {
+                    // Return cursor over specific set of values
+                    return getCursor(sTestValues1, 0);
+                }
+            }, null, 0);
+        } catch (OperationApplicationException e) {
+            fail("newAssert() failed");
+        }
+
+        ContentProviderOperation op3 = ContentProviderOperation.newAssertQuery(sTestUri1)
+                .withExpectedCount(2).build();
+
+        try {
+            // Assert that values match from cursor
+            ContentProviderResult result = op3.apply(new TestContentProvider() {
+                public Cursor query(Uri uri, String[] projection, String selection,
+                        String[] selectionArgs, String sortOrder) {
+                    // Return cursor over specific set of values
+                    return getCursor(sTestValues1, 5);
+                }
+            }, null, 0);
+            fail("we expect the exception to be thrown");
+        } catch (OperationApplicationException e) {
+        }
+    }
+
     /**
      * Build a {@link Cursor} with a single row that contains all values
      * provided through the given {@link ContentValues}.
      */
-    private Cursor getCursor(ContentValues contentValues) {
+    private Cursor getCursor(ContentValues contentValues, int numRows) {
         final Set<Entry<String, Object>> valueSet = contentValues.valueSet();
         final String[] keys = new String[valueSet.size()];
         final Object[] values = new Object[valueSet.size()];
@@ -170,7 +220,9 @@
         }
 
         final MatrixCursor cursor = new MatrixCursor(keys);
-        cursor.addRow(values);
+        for (i = 0; i < numRows; i++) {
+            cursor.addRow(values);
+        }
         return cursor;
     }
 
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index b00d8b0..b6b0e63 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -187,6 +187,13 @@
         return 0;
     }
 
+    // navigation hidden
+    if (getNavHiddenName(part.string(), &config)) {
+        *axis = AXIS_NAVHIDDEN;
+        *value = config.inputFlags;
+        return 0;
+    }
+
     // navigation
     if (getNavigationName(part.string(), &config)) {
         *axis = AXIS_NAVIGATION;
@@ -217,7 +224,7 @@
     Vector<String8> parts;
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
-    String8 touch, key, keysHidden, nav, size, vers;
+    String8 touch, key, keysHidden, nav, navHidden, size, vers;
 
     const char *p = dir;
     const char *q;
@@ -393,6 +400,19 @@
         //printf("not keyboard: %s\n", part.string());
     }
 
+    // navigation hidden
+    if (getNavHiddenName(part.string())) {
+        navHidden = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not navHidden: %s\n", part.string());
+    }
+
     if (getNavigationName(part.string())) {
         nav = part;
 
@@ -443,6 +463,7 @@
     this->touchscreen = touch;
     this->keysHidden = keysHidden;
     this->keyboard = key;
+    this->navHidden = navHidden;
     this->navigation = nav;
     this->screenSize = size;
     this->version = vers;
@@ -476,6 +497,8 @@
     s += ",";
     s += keyboard;
     s += ",";
+    s += navHidden;
+    s += ",";
     s += navigation;
     s += ",";
     s += screenSize;
@@ -528,6 +551,10 @@
         s += "-";
         s += keyboard;
     }
+    if (this->navHidden != "") {
+        s += "-";
+        s += navHidden;
+    }
     if (this->navigation != "") {
         s += "-";
         s += navigation;
@@ -852,6 +879,30 @@
     return false;
 }
 
+bool AaptGroupEntry::getNavHiddenName(const char* name,
+                                       ResTable_config* out)
+{
+    uint8_t mask = 0;
+    uint8_t value = 0;
+    if (strcmp(name, kWildcardName) == 0) {
+        mask = out->MASK_NAVHIDDEN;
+        value = out->NAVHIDDEN_ANY;
+    } else if (strcmp(name, "navexposed") == 0) {
+        mask = out->MASK_NAVHIDDEN;
+        value = out->NAVHIDDEN_NO;
+    } else if (strcmp(name, "navhidden") == 0) {
+        mask = out->MASK_NAVHIDDEN;
+        value = out->NAVHIDDEN_YES;
+    }
+
+    if (mask != 0) {
+        if (out) out->inputFlags = (out->inputFlags&~mask) | value;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getNavigationName(const char* name,
                                      ResTable_config* out)
 {
@@ -953,6 +1004,7 @@
     if (v == 0) v = touchscreen.compare(o.touchscreen);
     if (v == 0) v = keysHidden.compare(o.keysHidden);
     if (v == 0) v = keyboard.compare(o.keyboard);
+    if (v == 0) v = navHidden.compare(o.navHidden);
     if (v == 0) v = navigation.compare(o.navigation);
     if (v == 0) v = screenSize.compare(o.screenSize);
     if (v == 0) v = version.compare(o.version);
@@ -973,6 +1025,7 @@
     getTouchscreenName(touchscreen.string(), &params);
     getKeysHiddenName(keysHidden.string(), &params);
     getKeyboardName(keyboard.string(), &params);
+    getNavHiddenName(navHidden.string(), &params);
     getNavigationName(navigation.string(), &params);
     getScreenSizeName(screenSize.string(), &params);
     getVersionName(version.string(), &params);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 865efd1..26500a3 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -37,6 +37,7 @@
     AXIS_TOUCHSCREEN,
     AXIS_KEYSHIDDEN,
     AXIS_KEYBOARD,
+    AXIS_NAVHIDDEN,
     AXIS_NAVIGATION,
     AXIS_SCREENSIZE,
     AXIS_VERSION
@@ -64,6 +65,7 @@
     String8 touchscreen;
     String8 keysHidden;
     String8 keyboard;
+    String8 navHidden;
     String8 navigation;
     String8 screenSize;
     String8 version;
@@ -83,6 +85,7 @@
     static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
     static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
     static bool getNavigationName(const char* name, ResTable_config* out = NULL);
+    static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
     static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f85aadd..954930e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -42,24 +42,51 @@
     public static final String priorityVarName = "priority";
     /** {@hide} */
     public static final String hiddenSSIDVarName = "scan_ssid";
+
     /** {@hide} */
-    public static final String eapVarName = "eap";
+    public class EnterpriseField {
+        private String varName;
+        private String value;
+
+        private EnterpriseField(String varName) {
+            this.varName = varName;
+            this.value = null;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public String varName() {
+            return varName;
+        }
+
+        public String value() {
+            return value;
+        }
+    }
+
     /** {@hide} */
-    public static final String phase2VarName = "phase2";
+    public EnterpriseField eap = new EnterpriseField("eap");
     /** {@hide} */
-    public static final String identityVarName = "identity";
+    public EnterpriseField phase2 = new EnterpriseField("phase2");
     /** {@hide} */
-    public static final String anonymousIdentityVarName = "anonymous_identity";
+    public EnterpriseField identity = new EnterpriseField("anonymous_identity");
     /** {@hide} */
-    public static final String passwordVarName = "password";
+    public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
     /** {@hide} */
-    public static final String clientCertVarName = "client_cert";
+    public EnterpriseField password = new EnterpriseField("password");
     /** {@hide} */
-    public static final String caCertVarName = "ca_cert";
+    public EnterpriseField client_cert = new EnterpriseField("client_cert");
     /** {@hide} */
-    public static final String privateKeyVarName = "private_key";
+    public EnterpriseField private_key = new EnterpriseField("private_key");
     /** {@hide} */
-    public static final String privateKeyPasswdVarName = "private_key_passwd";
+    public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
+
+    /** {@hide} */
+    public EnterpriseField[] enterpriseFields = {
+            eap, phase2, identity, anonymous_identity, password, client_cert,
+            private_key, ca_cert };
 
     /**
      * Recognized key management schemes.
@@ -267,44 +294,6 @@
      */
     public BitSet allowedGroupCiphers;
 
-    /* The following fields are used for EAP/IEEE8021X authentication */
-
-    /**
-     * The eap mode should be PEAP, TLS or TTLS.
-     * {@hide}
-     */
-    public String eap;
-    /**
-     * The phase2 authenication could be PAP, MSCHAP, MSCHAP2, GTC.
-     * {@hide}
-     */
-    public String phase2;
-    /**
-     * The identity of the user in string,
-     * which is used for the authentication.
-     * {@hide}
-     */
-    public String identity;
-    /** {@hide} */
-    public String anonymousIdentity;
-    /** {@hide} */
-    public String password;
-    /** The path of the client certificate file.
-     * {@hide}
-     */
-    public String clientCert;
-    /** The path of the CA certificate file.
-     * {@hide}
-     */
-    public String caCert;
-    /** The path of the private key file.
-     * {@hide}
-     */
-    public String privateKey;
-    /** The password of the private key file if encrypted.
-     * {@hide}
-     */
-    public String privateKeyPasswd;
 
     public WifiConfiguration() {
         networkId = -1;
@@ -320,15 +309,9 @@
         wepKeys = new String[4];
         for (int i = 0; i < wepKeys.length; i++)
             wepKeys[i] = null;
-        eap = null;
-        phase2 = null;
-        identity = null;
-        anonymousIdentity = null;
-        password = null;
-        clientCert = null;
-        caCert = null;
-        privateKey = null;
-        privateKeyPasswd = null;
+        for (EnterpriseField field : enterpriseFields) {
+            field.setValue(null);
+        }
     }
 
     public String toString() {
@@ -403,41 +386,11 @@
         if (this.preSharedKey != null) {
             sbuf.append('*');
         }
-        sbuf.append('\n').append(" eap: ");
-        if (this.eap != null) {
-            sbuf.append(eap);
-        }
-        sbuf.append('\n').append(" phase2: ");
-        if (this.phase2 != null) {
-            sbuf.append(phase2);
-        }
-        sbuf.append('\n').append(" Identity: ");
-        if (this.identity != null) {
-            sbuf.append(identity);
-        }
-        sbuf.append('\n').append(" AnonymousIdentity: ");
-        if (this.anonymousIdentity != null) {
-            sbuf.append(anonymousIdentity);
-        }
-        sbuf.append('\n').append(" Password: ");
-        if (this.password != null) {
-            sbuf.append(password);
-        }
-        sbuf.append('\n').append(" ClientCert: ");
-        if (this.clientCert != null) {
-            sbuf.append(clientCert);
-        }
-        sbuf.append('\n').append(" CaCert: ");
-        if (this.caCert != null) {
-            sbuf.append(caCert);
-        }
-        sbuf.append('\n').append(" PrivateKey: ");
-        if (this.privateKey != null) {
-            sbuf.append(privateKey);
-        }
-        sbuf.append('\n').append(" PrivateKeyPasswd: ");
-        if (this.privateKeyPasswd != null) {
-            sbuf.append(privateKeyPasswd);
+
+        for (EnterpriseField field : enterpriseFields) {
+            sbuf.append('\n').append(" " + field.varName() + ": ");
+            String value = field.value();
+            if (value != null) sbuf.append(value);
         }
         sbuf.append('\n');
         return sbuf.toString();
@@ -497,15 +450,10 @@
         writeBitSet(dest, allowedAuthAlgorithms);
         writeBitSet(dest, allowedPairwiseCiphers);
         writeBitSet(dest, allowedGroupCiphers);
-        dest.writeString(eap);
-        dest.writeString(phase2);
-        dest.writeString(identity);
-        dest.writeString(anonymousIdentity);
-        dest.writeString(password);
-        dest.writeString(clientCert);
-        dest.writeString(caCert);
-        dest.writeString(privateKey);
-        dest.writeString(privateKeyPasswd);
+
+        for (EnterpriseField field : enterpriseFields) {
+            dest.writeString(field.value());
+        }
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -528,15 +476,10 @@
                 config.allowedAuthAlgorithms  = readBitSet(in);
                 config.allowedPairwiseCiphers = readBitSet(in);
                 config.allowedGroupCiphers    = readBitSet(in);
-                config.eap = in.readString();
-                config.phase2 = in.readString();
-                config.identity = in.readString();
-                config.anonymousIdentity = in.readString();
-                config.password = in.readString();
-                config.clientCert = in.readString();
-                config.caCert = in.readString();
-                config.privateKey = in.readString();
-                config.privateKeyPasswd = in.readString();
+
+                for (EnterpriseField field : config.enterpriseFields) {
+                    field.setValue(in.readString());
+                }
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 9a11404..e3d8bf4 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1350,7 +1350,7 @@
      */
     private synchronized void requestPolledInfo(WifiInfo info, boolean polling)
     {
-        int newRssi = WifiNative.getRssiCommand();
+        int newRssi = (polling ? WifiNative.getRssiApproxCommand() : WifiNative.getRssiCommand());
         if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
             /* some implementations avoid negative values by adding 256
              * so we need to adjust for that here.