Merge change I20d77880 into eclair-mr2

* changes:
  Make Gservices setting constants public.
diff --git a/api/current.xml b/api/current.xml
index 7057866..027bc1b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -34032,6 +34032,17 @@
 <parameter name="defaultValue" type="short">
 </parameter>
 </method>
+<method name="getSourceBounds"
+ return="android.graphics.Rect"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getStringArrayExtra"
  return="java.lang.String[]"
  abstract="false"
@@ -34843,6 +34854,19 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setSourceBounds"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="android.graphics.Rect">
+</parameter>
+</method>
 <method name="setType"
  return="android.content.Intent"
  abstract="false"
@@ -36423,6 +36447,17 @@
  visibility="public"
 >
 </field>
+<field name="FILL_IN_SOURCE_BOUNDS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_ACTIVITY_BROUGHT_TO_FRONT"
  type="int"
  transient="false"
@@ -62109,6 +62144,17 @@
  visibility="public"
 >
 </method>
+<method name="flattenToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="height"
  return="int"
  abstract="false"
@@ -62335,6 +62381,19 @@
  visibility="public"
 >
 </method>
+<method name="unflattenFromString"
+ return="android.graphics.Rect"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="str" type="java.lang.String">
+</parameter>
+</method>
 <method name="union"
  return="void"
  abstract="false"
diff --git a/calendar/Android.mk b/calendar/Android.mk
new file mode 100644
index 0000000..fd20dfa
--- /dev/null
+++ b/calendar/Android.mk
@@ -0,0 +1,18 @@
+# Copyright 2009 Google, Inc.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := calendar
+LOCAL_SRC_FILES := \
+	../core/java/android/provider/Calendar.java \
+	../core/java/android/pim/EventRecurrence.java \
+	../core/java/android/pim/ICalendar.java \
+	../core/java/android/pim/RecurrenceSet.java \
+	../core/java/android/pim/ContactsAsyncHelper.java \
+	../core/java/android/pim/DateException.java
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Include this library in the build server's output directory
+$(call dist-for-goals, droid, $(LOCAL_BUILT_MODULE):calendar.jar)
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 6cb9770..cf9c58f 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -624,6 +624,14 @@
         return false;
     }
 
+    /** @hide */
+    public boolean isBluetoothDock() {
+        try {
+            return sService.isBluetoothDock(mAddress);
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return false;
+    }
+
     /**
      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
      * outgoing connection to this remote device on given channel.
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 7e752af..0868779 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -64,6 +64,7 @@
 
     boolean setTrust(in String address, in boolean value);
     boolean getTrustState(in String address);
+    boolean isBluetoothDock(in String address);
 
     int addRfcommServiceRecord(in String serviceName, in ParcelUuid uuid, int channel, IBinder b);
     void removeServiceRecord(int handle);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6ba79b4..8d69814 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -2417,6 +2418,7 @@
     private int mFlags;
     private HashSet<String> mCategories;
     private Bundle mExtras;
+    private Rect mSourceBounds;
 
     // ---------------------------------------------------------------------
 
@@ -2442,6 +2444,9 @@
         if (o.mExtras != null) {
             this.mExtras = new Bundle(o.mExtras);
         }
+        if (o.mSourceBounds != null) {
+            this.mSourceBounds = new Rect(o.mSourceBounds);
+        }
     }
 
     @Override
@@ -2635,7 +2640,7 @@
                     intent.mType = value;
                 }
 
-                // launch  flags
+                // launch flags
                 else if (uri.startsWith("launchFlags=", i)) {
                     intent.mFlags = Integer.decode(value).intValue();
                 }
@@ -2655,6 +2660,11 @@
                     scheme = value;
                 }
 
+                // source bounds
+                else if (uri.startsWith("sourceBounds=", i)) {
+                    intent.mSourceBounds = Rect.unflattenFromString(value);
+                }
+
                 // extra
                 else {
                     String key = Uri.decode(uri.substring(i + 2, eq));
@@ -3547,6 +3557,15 @@
     }
 
     /**
+     * Get the bounds of the sender of this intent, in screen coordinates.  This can be
+     * used as a hint to the receiver for animations and the like.  Null means that there
+     * is no source bounds.
+     */
+    public Rect getSourceBounds() {
+        return mSourceBounds;
+    }
+
+    /**
      * Return the Activity component that should be used to handle this intent.
      * The appropriate component is determined based on the information in the
      * intent, evaluated as follows:
@@ -4648,6 +4667,19 @@
     }
 
     /**
+     * Set the bounds of the sender of this intent, in screen coordinates.  This can be
+     * used as a hint to the receiver for animations and the like.  Null means that there
+     * is no source bounds.
+     */
+    public void setSourceBounds(Rect r) {
+        if (r != null) {
+            mSourceBounds = new Rect(r);
+        } else {
+            r = null;
+        }
+    }
+
+    /**
      * Use with {@link #fillIn} to allow the current action value to be
      * overwritten, even if it is already set.
      */
@@ -4678,6 +4710,12 @@
     public static final int FILL_IN_PACKAGE = 1<<4;
 
     /**
+     * Use with {@link #fillIn} to allow the current package value to be
+     * overwritten, even if it is already set.
+     */
+    public static final int FILL_IN_SOURCE_BOUNDS = 1<<5;
+
+    /**
      * Copy the contents of <var>other</var> in to this object, but only
      * where fields are not defined by this object.  For purposes of a field
      * being defined, the following pieces of data in the Intent are
@@ -4691,6 +4729,7 @@
      * <li> package, as set by {@link #setPackage}.
      * <li> component, as set by {@link #setComponent(ComponentName)} or
      * related methods.
+     * <li> source bounds, as set by {@link #setSourceBounds}
      * <li> each top-level name in the associated extras.
      * </ul>
      *
@@ -4752,6 +4791,11 @@
             changes |= FILL_IN_COMPONENT;
         }
         mFlags |= other.mFlags;
+        if (other.mSourceBounds != null
+                && (mSourceBounds == null || (flags&FILL_IN_SOURCE_BOUNDS) != 0)) {
+            mSourceBounds = new Rect(other.mSourceBounds);
+            changes |= FILL_IN_SOURCE_BOUNDS;
+        }
         if (mExtras == null) {
             if (other.mExtras != null) {
                 mExtras = new Bundle(other.mExtras);
@@ -5005,6 +5049,13 @@
             first = false;
             b.append("cmp=").append(mComponent.flattenToShortString());
         }
+        if (mSourceBounds != null) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("bnds=").append(mSourceBounds.toShortString());
+        }
         if (extras && mExtras != null) {
             if (!first) {
                 b.append(' ');
@@ -5096,6 +5147,11 @@
             uri.append("component=").append(Uri.encode(
                     mComponent.flattenToShortString(), "/")).append(';');
         }
+        if (mSourceBounds != null) {
+            uri.append("sourceBounds=")
+                    .append(Uri.encode(mSourceBounds.flattenToString()))
+                    .append(';');
+        }
         if (mExtras != null) {
             for (String key : mExtras.keySet()) {
                 final Object value = mExtras.get(key);
@@ -5139,6 +5195,13 @@
         out.writeString(mPackage);
         ComponentName.writeToParcel(mComponent, out);
 
+        if (mSourceBounds != null) {
+            out.writeInt(1);
+            mSourceBounds.writeToParcel(out, flags);
+        } else {
+            out.writeInt(0);
+        }
+
         if (mCategories != null) {
             out.writeInt(mCategories.size());
             for (String category : mCategories) {
@@ -5174,6 +5237,10 @@
         mPackage = in.readString();
         mComponent = ComponentName.readFromParcel(in);
 
+        if (in.readInt() != 0) {
+            mSourceBounds = Rect.CREATOR.createFromParcel(in);
+        }
+
         int N = in.readInt();
         if (N > 0) {
             mCategories = new HashSet<String>();
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 657bbcc..d9003a3 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -827,6 +827,15 @@
     }
 
     private void closeClosable() {
+        /* deallocate all compiled sql statement objects in compiledQueries cache.
+         * this should be done before de-referencing all {@link SQLiteClosable} objects
+         * from this database object because calling
+         * {@link SQLiteClosable#onAllReferencesReleasedFromContainer()} could cause the database
+         * to be closed. sqlite doesn't let a database close if there are
+         * any unfinalized statements - such as the compiled-sql objects in mCompiledQueries.
+         */
+        resetCompiledSqlCache();
+ 
         Iterator<Map.Entry<SQLiteClosable, Object>> iter = mPrograms.entrySet().iterator();
         while (iter.hasNext()) {
             Map.Entry<SQLiteClosable, Object> entry = iter.next();
@@ -835,13 +844,6 @@
                 program.onAllReferencesReleasedFromContainer();
             }
         }
-
-        // finalize all compiled sql statement objects in compiledQueries cache
-        synchronized (mCompiledQueries) {
-            for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
-                compiledStatement.releaseSqlStatement();
-            }
-        }
     }
 
     /**
@@ -1789,7 +1791,9 @@
      */
     public void setMaxSqlCacheSize(int cacheSize) {
         synchronized(mCompiledQueries) {
-            resetCompiledSqlCache();
+            if (mMaxSqlCacheSize > 0) {
+                resetCompiledSqlCache();
+            }
             mMaxSqlCacheSize = (cacheSize > MAX_SQL_CACHE_SIZE) ? MAX_SQL_CACHE_SIZE
                     : (cacheSize < 0) ? 0 : cacheSize;
         }
@@ -1800,6 +1804,9 @@
      */
     public void resetCompiledSqlCache() {
         synchronized(mCompiledQueries) {
+            for (SQLiteCompiledSql compiledStatement : mCompiledQueries.values()) {
+                compiledStatement.releaseSqlStatement();
+            }
             mCompiledQueries.clear();
         }
     }
@@ -1835,7 +1842,7 @@
                 /* reached max cachesize. before adding new entry, remove an entry from the
                  * cache. we don't want to wipe out the entire cache because of this:
                  * GCing {@link SQLiteCompiledSql} requires call to sqlite3_finalize
-                 * JNI method. If entire cache is wiped out, it could be cause a big GC activity
+                 * JNI method. If entire cache is wiped out, it could cause a big GC activity
                  * just because a (rogue) process is using the cache incorrectly.
                  */
                 Set<String> keySet = mCompiledQueries.keySet();
@@ -1844,8 +1851,7 @@
                     break;
                 }
             }
-            compiledSql = new SQLiteCompiledSql(this, sql);
-            mCompiledQueries.put(sql, compiledSql);
+            mCompiledQueries.put(sql, compiledStatement);
         }
         if (SQLiteDebug.DEBUG_SQL_CACHE) {
             Log.v(TAG, "|adding_sql_to_cache|" + getPath() + "|" + mCompiledQueries.size() + "|" +
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index edc15cb..5ee2f1e 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -100,7 +100,7 @@
      * @return a unique identifier for this program
      */
     public final int getUniqueId() {
-        return compiledSql.nStatement;
+        return  (compiledSql != null) ? compiledSql.nStatement : 0;
     }
 
     /* package */ String getSqlString() {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 4b733ef..ac159f4 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -477,6 +477,10 @@
      * application does not need a particular callback, a null can be passed
      * instead of a callback method.
      *
+     * This method will stop the preview. Applications should not call {@link
+     * #stopPreview()} before this. After jpeg callback is received,
+     * applications can call {@link #startPreview()} to restart the preview.
+     *
      * @param shutter   callback after the image is captured, may be null
      * @param raw       callback with raw image data, may be null
      * @param jpeg      callback with jpeg image data, may be null
@@ -500,6 +504,10 @@
      * application does not need a particular callback, a null can be passed
      * instead of a callback method.
      *
+     * This method will stop the preview. Applications should not call {@link
+     * #stopPreview()} before this. After jpeg callback is received,
+     * applications can call {@link #startPreview()} to restart the preview.
+     *
      * @param shutter   callback after the image is captured, may be null
      * @param raw       callback with raw image data, may be null
      * @param postview  callback with postview image data, may be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index c3b0f1c..30c73d7 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -293,6 +293,13 @@
         public static final String DISPLAY_NAME = "display_name";
 
         /**
+         * Reference to the row in the RawContacts table holding the contact name.
+         * <P>Type: INTEGER REFERENCES raw_contacts(_id)</P>
+         * @hide
+         */
+        public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id";
+
+        /**
          * Reference to the row in the data table holding the photo.
          * <P>Type: INTEGER REFERENCES data(_id)</P>
          */
@@ -423,13 +430,21 @@
      * row id changed as a result of a sync or aggregation.</td>
      * </tr>
      * <tr>
+     * <td>long</td>
+     * <td>NAME_RAW_CONTACT_ID</td>
+     * <td>read-only</td>
+     * <td>The ID of the raw contact that contributes the display name
+     * to the aggregate contact. During aggregation one of the constituent
+     * raw contacts is chosen using a heuristic: a longer name or a name
+     * with more diacritic marks or more upper case characters is chosen.</td>
+     * </tr>
+     * <tr>
      * <td>String</td>
      * <td>{@link #DISPLAY_NAME}</td>
      * <td>read-only</td>
-     * <td>The display name for the contact. During aggregation display name is
-     * computed from display names of constituent raw contacts using a
-     * heuristic: a longer name or a name with more diacritic marks or more
-     * upper case characters is chosen.</td>
+     * <td>The display name for the contact. It is the display name
+     * contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID
+     * column.</td>
      * </tr>
      * <tr>
      * <td>long</td>
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6380a8d..4860cbd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -553,7 +553,8 @@
              *   <li><em>transactionId (Integer)</em> - The WAP transaction
              *    ID</li>
              *   <li><em>pduType (Integer)</em> - The WAP PDU type</li>
-             *   <li><em>data</em> - The data payload of the message</li>
+             *   <li><em>header (byte[])</em> - The header of the message</li>
+             *   <li><em>data (byte[])</em> - The data payload of the message</li>
              * </ul>
              *
              * <p>If a BroadcastReceiver encounters an error while processing
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index cb3b6ee..e960491 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -492,6 +492,14 @@
                 mBluetoothService.getBondState().getPendingOutgoingBonding();
         if (address.equals(pendingOutgoingAddress)) {
             // we initiated the bonding
+
+            // Check if its a dock
+            if (mBluetoothService.isBluetoothDock(address)) {
+                String pin = mBluetoothService.getDockPin();
+                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes(pin));
+                return;
+            }
+
             BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address));
 
             // try 0000 once if the device looks dumb
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index f8592e2..5dd016f 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -32,16 +32,16 @@
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
-import android.os.ParcelUuid;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Binder;
-import android.os.IBinder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemService;
@@ -50,7 +50,13 @@
 
 import com.android.internal.app.IBatteryStats;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedWriter;
 import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
@@ -58,6 +64,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Random;
 
 public class BluetoothService extends IBluetooth.Stub {
     private static final String TAG = "BluetoothService";
@@ -79,6 +86,9 @@
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
 
+    private static final String DOCK_ADDRESS_PATH = "/sys/class/switch/dock/bt_addr";
+    private static final String DOCK_PIN_PATH = "/sys/class/switch/dock/bt_pin";
+
     private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
     private static final int MESSAGE_FINISH_DISABLE = 2;
     private static final int MESSAGE_UUID_INTENT = 3;
@@ -104,6 +114,9 @@
 
     private final HashMap<Integer, Integer> mServiceRecordToPid;
 
+    private static String mDockAddress;
+    private String mDockPin;
+
     private static class RemoteService {
         public String address;
         public ParcelUuid uuid;
@@ -151,6 +164,96 @@
         mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
         mServiceRecordToPid = new HashMap<Integer, Integer>();
         registerForAirplaneMode();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_DOCK_EVENT);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent != null) {
+                String action = intent.getAction();
+
+                if (Intent.ACTION_DOCK_EVENT.equals(action)) {
+                    int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                            Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                    if (DBG) Log.v(TAG, "Received ACTION_DOCK_EVENT with State:" + state);
+                    if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                        mDockAddress = null;
+                        mDockPin = null;
+                    }
+                }
+            }
+        }
+    };
+
+     public static synchronized String readDockBluetoothAddress() {
+        if (mDockAddress != null) return mDockAddress;
+
+        BufferedInputStream file = null;
+        String dockAddress;
+        try {
+            file = new BufferedInputStream(new FileInputStream(DOCK_ADDRESS_PATH));
+            byte[] address = new byte[17];
+            file.read(address);
+            dockAddress = new String(address);
+            dockAddress = dockAddress.toUpperCase();
+            if (BluetoothAdapter.checkBluetoothAddress(dockAddress)) {
+                mDockAddress = dockAddress;
+                return mDockAddress;
+            } else {
+                log("CheckBluetoothAddress failed for car dock address:" + dockAddress);
+            }
+        } catch (FileNotFoundException e) {
+            log("FileNotFoundException while trying to read dock address");
+        } catch (IOException e) {
+            log("IOException while trying to read dock address");
+        } finally {
+            if (file != null) {
+                try {
+                    file.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+        mDockAddress = null;
+        return null;
+    }
+
+    private synchronized boolean writeDockPin() {
+        BufferedWriter out = null;
+        try {
+            out = new BufferedWriter(new FileWriter(DOCK_PIN_PATH));
+
+            // Generate a random 4 digit pin between 0000 and 9999
+            // This is not truly random but good enough for our purposes.
+            int pin = (int) Math.floor(Math.random() * 10000);
+
+            mDockPin = String.format("%04d", pin);
+            out.write(mDockPin);
+            return true;
+        } catch (FileNotFoundException e) {
+            log("FileNotFoundException while trying to write dock pairing pin");
+        } catch (IOException e) {
+            log("IOException while while trying to write dock pairing pin");
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+        mDockPin = null;
+        return false;
+    }
+
+    /*package*/ synchronized String getDockPin() {
+        return mDockPin;
     }
 
     public synchronized void initAfterRegistration() {
@@ -922,6 +1025,13 @@
             return false;
         }
 
+        if (address.equals(mDockAddress)) {
+            if (!writeDockPin()) {
+                log("Error while writing Pin for the dock");
+                return false;
+            }
+        }
+
         if (!createPairedDeviceNative(address, 60000 /* 1 minute */)) {
             return false;
         }
@@ -975,6 +1085,11 @@
         return mBondState.getBondState(address.toUpperCase());
     }
 
+    public synchronized boolean isBluetoothDock(String address) {
+        if (address.equals(mDockAddress)) return true;
+        return false;
+    }
+
     /*package*/ boolean isRemoteDeviceInCache(String address) {
         return (mDeviceProperties.get(address) != null);
     }
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 6995107..aa8d979 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -20,6 +20,7 @@
 import android.text.NoCopySpan;
 import android.text.Layout.Alignment;
 import android.text.Spannable;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.widget.TextView;
@@ -156,8 +157,17 @@
                                                             padding));
                     ny = Math.max(ny, 0);
         
+                    int oldX = widget.getScrollX();
+                    int oldY = widget.getScrollY();
+
                     scrollTo(widget, layout, nx, ny);
-                    widget.cancelLongPress();
+
+                    // If we actually scrolled, then cancel the up action.
+                    if (oldX != widget.getScrollX()
+                            || oldY != widget.getScrollY()) {
+                        widget.cancelLongPress();
+                    }
+
                     return true;
                 }
             }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b8bd6a0..5d3840a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -361,6 +361,8 @@
     public final int OFF_BECAUSE_OF_USER = 1;
     /** Screen turned off because of timeout */
     public final int OFF_BECAUSE_OF_TIMEOUT = 2;
+    /** Screen turned off because of proximity sensor */
+    public final int OFF_BECAUSE_OF_PROX_SENSOR = 3;
 
     /**
      * Magic constant to {@link IWindowManager#setRotation} to not actually
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6f15c12..7885b8a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3241,24 +3241,29 @@
             mWebTextView.setNodePointer(nodePointer);
             int maxLength = -1;
             boolean isTextField = nativeFocusCandidateIsTextField();
+            boolean isPassword;
             if (isTextField) {
                 maxLength = nativeFocusCandidateMaxLength();
                 String name = nativeFocusCandidateName();
-                if (mWebViewCore.getSettings().getSaveFormData()
-                        && name != null) {
+                isPassword = nativeFocusCandidateIsPassword();
+                if (!isPassword && mWebViewCore.getSettings().getSaveFormData()
+                        && name != null && name.length() > 0) {
                     Message update = mPrivateHandler.obtainMessage(
-                            REQUEST_FORM_DATA, nodePointer);
+                            REQUEST_FORM_DATA);
+                    update.arg1 = nodePointer;
                     RequestFormData updater = new RequestFormData(name,
                             getUrl(), update);
                     Thread t = new Thread(updater);
                     t.start();
                 }
+            } else {
+                isPassword = false;
             }
             mWebTextView.setMaxLength(maxLength);
             AutoCompleteAdapter adapter = null;
             mWebTextView.setAdapterCustom(adapter);
             mWebTextView.setSingleLine(isTextField);
-            mWebTextView.setInPassword(nativeFocusCandidateIsPassword());
+            mWebTextView.setInPassword(isPassword);
             if (null == text) {
                 if (DebugFlags.WEB_VIEW) {
                     Log.v(LOGTAG, "rebuildWebTextView null == text");
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 3b1f7a0..b847e57 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -23,6 +23,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Parcel;
@@ -136,10 +137,15 @@
             if (target != null && pendingIntent != null) {
                 OnClickListener listener = new OnClickListener() {
                     public void onClick(View v) {
+                        int[] pos = new int[2];
+                        v.getLocationOnScreen(pos);
+                        Intent intent = new Intent();
+                        intent.setSourceBounds(new Rect(pos[0], pos[1],
+                                    pos[0]+v.getWidth(), pos[1]+v.getHeight()));
                         try {
                             // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                             v.getContext().startIntentSender(
-                                    pendingIntent.getIntentSender(), null,
+                                    pendingIntent.getIntentSender(), intent,
                                     Intent.FLAG_ACTIVITY_NEW_TASK,
                                     Intent.FLAG_ACTIVITY_NEW_TASK, 0);
                         } catch (IntentSender.SendIntentException e) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f55ca3f..201cc0c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6529,6 +6529,7 @@
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
             mTouchFocusSelected = false;
+            mScrolled = false;
         }
         
         final boolean superResult = super.onTouchEvent(event);
@@ -6545,10 +6546,6 @@
 
         if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
             
-            if (action == MotionEvent.ACTION_DOWN) {
-                mScrolled = false;
-            }
-            
             boolean handled = false;
             
             int oldSelStart = Selection.getSelectionStart(mText);
diff --git a/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..617dba3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_lock_normal.9.png b/core/res/res/drawable-hdpi/btn_lock_normal.9.png
deleted file mode 100644
index f1dac62..0000000
--- a/core/res/res/drawable-hdpi/btn_lock_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_half.png b/core/res/res/drawable-hdpi/rate_star_big_half.png
index 61906a5..4a91e87 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_off.png b/core/res/res/drawable-hdpi/rate_star_big_off.png
index a688a45..ae5883e 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_big_on.png b/core/res/res/drawable-hdpi/rate_star_big_on.png
index 77cb067..65c136e 100644
--- a/core/res/res/drawable-hdpi/rate_star_big_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_big_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_half.png b/core/res/res/drawable-hdpi/rate_star_med_half.png
new file mode 100644
index 0000000..a436980
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_off.png b/core/res/res/drawable-hdpi/rate_star_med_off.png
new file mode 100644
index 0000000..981aabe
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_med_on.png b/core/res/res/drawable-hdpi/rate_star_med_on.png
new file mode 100644
index 0000000..320c14f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/rate_star_med_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_half.png b/core/res/res/drawable-hdpi/rate_star_small_half.png
index 6b2efd9..0b8974e1 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_half.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_off.png b/core/res/res/drawable-hdpi/rate_star_small_off.png
index 8422919..7ae305f 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_off.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/rate_star_small_on.png b/core/res/res/drawable-hdpi/rate_star_small_on.png
index 45e2324..ffa5258 100644
--- a/core/res/res/drawable-hdpi/rate_star_small_on.png
+++ b/core/res/res/drawable-hdpi/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..3b3dea9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_lock_normal.9.png b/core/res/res/drawable-mdpi/btn_lock_normal.9.png
deleted file mode 100644
index 6bdc2c6..0000000
--- a/core/res/res/drawable-mdpi/btn_lock_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/btn_default_transparent.xml b/core/res/res/drawable/btn_default_transparent.xml
new file mode 100644
index 0000000..f8e03ee
--- /dev/null
+++ b/core/res/res/drawable/btn_default_transparent.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" 
+        android:drawable="@drawable/btn_default_pressed" />
+    <item android:state_focused="true" android:state_enabled="true"
+        android:drawable="@drawable/btn_default_selected" />
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_default_transparent_normal" />
+</selector>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 26b77bb..f8944b5 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -136,8 +136,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/screenLocked"
-        android:layout_marginTop="24dip"
+        android:layout_marginTop="8dip"
+        android:layout_marginLeft="24dip"
         android:drawableLeft="@drawable/ic_emergency"
+        style="@style/Widget.Button.Transparent"
         android:drawablePadding="8dip"
        />
 
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 5c80235..22c0b8e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -128,8 +128,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_below="@id/screenLocked"
-            android:layout_marginTop="24dip"
+            android:layout_marginTop="8dip"
             android:drawableLeft="@drawable/ic_emergency"
+            style="@style/Widget.Button.Transparent"
             android:drawablePadding="8dip"
            />
     </RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 6da82e9..602a37c 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -155,10 +155,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/lockscreen_emergency_call"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:drawableLeft="@drawable/ic_emergency"
                     android:drawablePadding="8dip"
                     />
@@ -174,20 +171,14 @@
                 <Button android:id="@+id/forgotPattern"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:visibility="invisible"
                     />
                 <Button android:id="@+id/emergencyCallTogether"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/lockscreen_emergency_call"
-                    android:textSize="14sp"
-                    android:background="@drawable/btn_lock_normal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:textColor="?android:attr/textColorPrimary"
+                    style="@style/Widget.Button.Transparent"
                     android:drawableLeft="@drawable/ic_emergency"
                     android:drawablePadding="8dip"
                     />
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 5916786..9ce5a25 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -165,9 +165,7 @@
                 android:layout_height="wrap_content"
                 android:layout_centerInParent="true"
                 android:text="@string/lockscreen_emergency_call"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 />
@@ -190,9 +188,7 @@
                 android:layout_marginLeft="4dip"
                 android:layout_marginRight="2dip"
                 android:text="@string/lockscreen_emergency_call"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:drawableLeft="@drawable/ic_emergency"
                 android:drawablePadding="8dip"
                 />
@@ -204,9 +200,7 @@
                 android:layout_marginBottom="4dip"
                 android:layout_marginLeft="2dip"
                 android:layout_marginRight="4dip"
-                android:background="@drawable/btn_lock_normal"
-                android:textAppearance="?android:attr/textAppearanceSmall"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/Widget.Button.Transparent"
                 android:visibility="invisible"
                 />
         </LinearLayout>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a629bb2..c95ede7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -237,6 +237,12 @@
         <item name="android:background">@android:drawable/button_inset</item>
     </style>
 
+    <style name="Widget.Button.Transparent">
+        <item name="android:background">@android:drawable/btn_default_transparent</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
     <style name="Widget.CompoundButton">
         <item name="android:focusable">true</item>
         <item name="android:clickable">true</item>
diff --git a/docs/html/guide/samples/images/BluetoothChat1.png b/docs/html/guide/samples/images/BluetoothChat1.png
new file mode 100644
index 0000000..f87da6a
--- /dev/null
+++ b/docs/html/guide/samples/images/BluetoothChat1.png
Binary files differ
diff --git a/docs/html/guide/samples/images/BluetoothChat2.png b/docs/html/guide/samples/images/BluetoothChat2.png
new file mode 100644
index 0000000..6218eff
--- /dev/null
+++ b/docs/html/guide/samples/images/BluetoothChat2.png
Binary files differ
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index fc0061d..c9df3ba 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -124,9 +124,9 @@
 
 <pre>
 &lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
-    android:minWidth="294dp" &lt;!-- density-independent pixels --&gt;
+    android:minWidth="294dp"
     android:minHeight="72dp"
-    android:updatePeriodMillis="86400000" &lt;!-- once per day --&gt;
+    android:updatePeriodMillis="86400000"
     android:initialLayout="@layout/example_appwidget"
     android:configure="com.example.android.ExampleAppWidgetConfigure" >
 &lt;/appwidget-provider>
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 42a14ce..98ffb8b 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -20,6 +20,8 @@
 import android.os.Parcelable;
 
 import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Rect holds four integer coordinates for a rectangle. The rectangle is
@@ -34,6 +36,9 @@
     public int right;
     public int bottom;
 
+    private static final Pattern FLATTENED_PATTERN = Pattern.compile(
+            "(-?\\d+) (-?\\d+) (-?\\d+) (-?\\d+)");
+
     /**
      * Create a new empty Rect. All coordinates are initialized to 0.
      */
@@ -105,6 +110,43 @@
         sb.append(','); sb.append(bottom); sb.append(']');
         return sb.toString();
     }
+
+    /**
+     * Return a string representation of the rectangle in a well-defined format.
+     *
+     * <p>You can later recover the Rect from this string through
+     * {@link #unflattenFromString(String)}.
+     * 
+     * @return Returns a new String of the form "left top right bottom"
+     */
+    public String flattenToString() {
+        StringBuilder sb = new StringBuilder(32);
+        // WARNING: Do not change the format of this string, it must be
+        // preserved because Rects are saved in this flattened format.
+        sb.append(left);
+        sb.append(' ');
+        sb.append(top);
+        sb.append(' ');
+        sb.append(right);
+        sb.append(' ');
+        sb.append(bottom);
+        return sb.toString();
+    }
+
+    /**
+     * Returns a Rect from a string of the form returned by {@link #flattenToString},
+     * or null if the string is not of that form.
+     */
+    public static Rect unflattenFromString(String str) {
+        Matcher matcher = FLATTENED_PATTERN.matcher(str);
+        if (!matcher.matches()) {
+            return null;
+        }
+        return new Rect(Integer.parseInt(matcher.group(1)),
+                Integer.parseInt(matcher.group(2)),
+                Integer.parseInt(matcher.group(3)),
+                Integer.parseInt(matcher.group(4)));
+    }
     
     /**
      * Print short representation to given writer.
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 88ef7e4..eb017bf 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -266,7 +266,16 @@
     : mBufferHeap(buffers)
 {
     NativeBuffer& src(mNativeBuffer);
-    src.img.handle = 0;
+    src.crop.l = 0;
+    src.crop.t = 0;
+    src.crop.r = buffers.w;
+    src.crop.b = buffers.h;
+
+    src.img.w       = buffers.hor_stride ?: buffers.w;
+    src.img.h       = buffers.ver_stride ?: buffers.h;
+    src.img.format  = buffers.format;
+    src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
+    src.img.handle  = 0;
 
     gralloc_module_t const * module = LayerBuffer::getGrallocModule();
     if (module && module->perform) {
@@ -276,19 +285,12 @@
                 offset, buffers.heap->base(),
                 &src.img.handle);
 
-        if (err == NO_ERROR) {
-            src.crop.l = 0;
-            src.crop.t = 0;
-            src.crop.r = buffers.w;
-            src.crop.b = buffers.h;
-
-            src.img.w       = buffers.hor_stride ?: buffers.w;
-            src.img.h       = buffers.ver_stride ?: buffers.h;
-            src.img.format  = buffers.format;
-            src.img.base    = (void*)(intptr_t(buffers.heap->base()) + offset);
-        }
+        LOGE_IF(err, "CREATE_HANDLE_FROM_BUFFER (heapId=%d, size=%d, "
+             "offset=%ld, base=%p) failed (%s)",
+                buffers.heap->heapID(), buffers.heap->getSize(),
+                offset, buffers.heap->base(), strerror(-err));
     }
-}
+ }
 
 LayerBuffer::Buffer::~Buffer()
 {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 6cd4b92..c49ad5c 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -22,6 +22,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.TimeZone;
 
 /**
  * This is a class for reading and writing Exif tags in a JPEG file.
@@ -56,9 +57,12 @@
     // Constants used for white balance
     public static final int WHITEBALANCE_AUTO = 0;
     public static final int WHITEBALANCE_MANUAL = 1;
+    private static SimpleDateFormat sFormatter;
 
     static {
         System.loadLibrary("exif");
+        sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+        sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
     }
 
     private String mFilename;
@@ -242,9 +246,6 @@
         }
     }
 
-    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.
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b81684b..a4e3601 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -202,7 +202,6 @@
 };
 
 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
-/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 0;
 /* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
 /* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
 
@@ -1485,7 +1484,7 @@
     LOGV("setVolume");
     t->setVolume(mLeftVolume, mRightVolume);
     mMsecsPerFrame = 1.e3 / (float) sampleRate;
-    mLatency = t->latency() + kAudioVideoDelayMs;
+    mLatency = t->latency();
     mTrack = t;
     return NO_ERROR;
 }
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index b00f5b7..1c90cf9 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -108,8 +108,6 @@
         float                   mMsecsPerFrame;
         uint32_t                mLatency;
 
-        // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
-        static const uint32_t   kAudioVideoDelayMs;
         static bool             mIsOnEmulator;
         static int              mMinBufferCount;  // 12 for emulator; otherwise 4
 
diff --git a/opengl/java/android/opengl/GLLogWrapper.java b/opengl/java/android/opengl/GLLogWrapper.java
index 4119bf8..f332448 100644
--- a/opengl/java/android/opengl/GLLogWrapper.java
+++ b/opengl/java/android/opengl/GLLogWrapper.java
@@ -1517,7 +1517,7 @@
         arg("count", count);
         startLogIndices();
         for (int i = 0; i < count; i++) {
-            doElement(mStringBuilder, i, first + count);
+            doElement(mStringBuilder, i, first + i);
         }
         endLogIndices();
         end();
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index c2b1b96..2fff54c 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -18,6 +18,8 @@
 
 import android.app.Activity;
 import android.app.KeyguardManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -27,12 +29,13 @@
 import android.os.SystemClock;
 import android.os.UEventObserver;
 import android.provider.Settings;
+import android.server.BluetoothService;
 import android.util.Log;
 
 import com.android.internal.widget.LockPatternUtils;
 
-import java.io.FileReader;
 import java.io.FileNotFoundException;
+import java.io.FileReader;
 
 /**
  * <p>DockObserver monitors for a docking station.
@@ -65,7 +68,7 @@
             if (getResultCode() != Activity.RESULT_OK) {
                 return;
             }
-            
+
             // Launch a dock activity
             String category;
             switch (mDockState) {
@@ -177,7 +180,13 @@
                 // Pack up the values and broadcast them to everyone
                 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
                 intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
-                
+
+                // Check if this is Bluetooth Dock
+                String address = BluetoothService.readDockBluetoothAddress();
+                if (address != null)
+                    intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
+                            BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
+
                 // Send the ordered broadcast; the result receiver will receive after all
                 // broadcasts have been sent. If any broadcast receiver changes the result
                 // code from the initial value of RESULT_OK, then the result receiver will
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 7c19f24..6f207e0 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -313,14 +313,17 @@
             long bestDistance = -1;
             int bestIndex = -1;
             for (int j=0; j<lastNumPointers; j++) {
-                if (!allowOverlap && last2Next[j] < 0) {
+                // If we are not allowing multiple new points to be assigned
+                // to the same old pointer, then skip this one if it is already
+                // detected as a conflict (-2).
+                if (!allowOverlap && last2Next[j] < -1) {
                     continue;
                 }
                 final int jd = j * MotionEvent.NUM_SAMPLE_DATA;
                 final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1;
                 final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1;
                 final long distance = xd*(long)xd + yd*(long)yd;
-                if (j == 0 || distance < bestDistance) {
+                if (bestDistance == -1 || distance < bestDistance) {
                     bestDistance = distance;
                     bestIndex = j;
                 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index cb8cb7f..147580b 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -99,7 +99,11 @@
     private NotificationRecord mVibrateNotification;
     private Vibrator mVibrator = new Vibrator();
 
-    // adb
+    // for enabling and disabling notification pulse behavior
+    private boolean mScreenOn = true;
+    private boolean mNotificationPulseEnabled;
+
+    // for adb connected notifications
     private boolean mUsbConnected;
     private boolean mAdbEnabled = false;
     private boolean mAdbNotificationShown = false;
@@ -336,6 +340,12 @@
                     return;
                 }
                 cancelAllNotificationsInt(pkgName, 0, 0);
+            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                mScreenOn = true;
+                updateNotificationPulse();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mScreenOn = false;
+                updateNotificationPulse();
             }
         }
     };
@@ -349,6 +359,8 @@
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.ADB_ENABLED), false, this);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.NOTIFICATION_LIGHT_PULSE), false, this);
             update();
         }
 
@@ -358,13 +370,21 @@
 
         public void update() {
             ContentResolver resolver = mContext.getContentResolver();
-            mAdbEnabled = Settings.Secure.getInt(resolver,
+            boolean adbEnabled = Settings.Secure.getInt(resolver,
                         Settings.Secure.ADB_ENABLED, 0) != 0;
-            updateAdbNotification();
+            if (mAdbEnabled != adbEnabled) {
+                mAdbEnabled = adbEnabled;
+                updateAdbNotification();
+            }
+            boolean pulseEnabled = Settings.System.getInt(resolver,
+                        Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
+            if (mNotificationPulseEnabled != pulseEnabled) {
+                mNotificationPulseEnabled = pulseEnabled;
+                updateNotificationPulse();
+            }
         }
     }
-    private final SettingsObserver mSettingsObserver;
-    
+
     NotificationManagerService(Context context, StatusBarService statusBar,
             LightsService lights)
     {
@@ -399,10 +419,12 @@
         filter.addAction(Intent.ACTION_UMS_DISCONNECTED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
         mContext.registerReceiver(mIntentReceiver, filter);
         
-        mSettingsObserver = new SettingsObserver(mHandler);
-        mSettingsObserver.observe();
+        SettingsObserver observer = new SettingsObserver(mHandler);
+        observer.observe();
     }
 
     void systemReady() {
@@ -1005,7 +1027,9 @@
                 mLedNotification = mLights.get(n-1);
             }
         }
-        if (mLedNotification == null) {
+
+        // we only flash if screen is off and persistent pulsing is enabled
+        if (mLedNotification == null || mScreenOn || !mNotificationPulseEnabled) {
             mNotificationLight.turnOff();
         } else {
             mNotificationLight.setFlashing(
@@ -1097,7 +1121,13 @@
             }
         }
     }
-    
+
+    private void updateNotificationPulse() {
+        synchronized (mNotificationList) {
+            updateLightsLocked();
+        }
+    }
+
     // ======================================================================
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 8584d74..6e769c7 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -161,7 +161,9 @@
     private int[] mBroadcastWhy = new int[3];
     private int mPartialCount = 0;
     private int mPowerState;
-    private boolean mOffBecauseOfUser;
+    // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
+    // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
+    private int mScreenOffReason;
     private int mUserState;
     private boolean mKeyboardVisible = false;
     private boolean mUserActivityAllowed = true;
@@ -919,7 +921,7 @@
                 + " " + ((mNextTimeout-now)/1000) + "s from now");
         pw.println("  mDimScreen=" + mDimScreen
                 + " mStayOnConditions=" + mStayOnConditions);
-        pw.println("  mOffBecauseOfUser=" + mOffBecauseOfUser
+        pw.println("  mScreenOffReason=" + mScreenOffReason
                 + " mUserState=" + mUserState);
         pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
                 + ',' + mBroadcastQueue[2] + "}");
@@ -1384,10 +1386,10 @@
 
     private void setPowerState(int state)
     {
-        setPowerState(state, false, false);
+        setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
     }
 
-    private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
+    private void setPowerState(int newState, boolean noChangeLights, int reason)
     {
         synchronized (mLocks) {
             int err;
@@ -1395,7 +1397,8 @@
             if (mSpew) {
                 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
                         + " newState=0x" + Integer.toHexString(newState)
-                        + " noChangeLights=" + noChangeLights);
+                        + " noChangeLights=" + noChangeLights
+                        + " reason=" + reason);
             }
 
             if (noChangeLights) {
@@ -1489,7 +1492,7 @@
                     mLastTouchDown = 0;
                     mTotalTouchDownTime = 0;
                     mTouchCycles = 0;
-                    EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
+                    EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, reason,
                             mTotalTouchDownTime, mTouchCycles);
                     if (err == 0) {
                         mPowerState |= SCREEN_ON_BIT;
@@ -1508,10 +1511,10 @@
                         Binder.restoreCallingIdentity(identity);
                     }
                     mPowerState &= ~SCREEN_ON_BIT;
+                    mScreenOffReason = reason;
                     if (!mScreenBrightness.animating) {
-                        err = screenOffFinishedAnimatingLocked(becauseOfUser);
+                        err = screenOffFinishedAnimatingLocked(reason);
                     } else {
-                        mOffBecauseOfUser = becauseOfUser;
                         err = 0;
                         mLastTouchDown = 0;
                     }
@@ -1520,19 +1523,16 @@
         }
     }
     
-    private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) {
+    private int screenOffFinishedAnimatingLocked(int reason) {
         // I don't think we need to check the current state here because all of these
         // Power.setScreenState and sendNotificationLocked can both handle being 
         // called multiple times in the same state. -joeo
-        EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
-                mTotalTouchDownTime, mTouchCycles);
+        EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
         mLastTouchDown = 0;
         int err = setScreenStateLocked(false);
         if (err == 0) {
-            int why = becauseOfUser
-                    ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
-                    : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
-            sendNotificationLocked(false, why);
+            mScreenOffReason = reason;
+            sendNotificationLocked(false, reason);
         }
         return err;
     }
@@ -1808,7 +1808,7 @@
             animating = more;
             if (!more) {
                 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
-                    screenOffFinishedAnimatingLocked(mOffBecauseOfUser);
+                    screenOffFinishedAnimatingLocked(mScreenOffReason);
                 }
             }
             return more;
@@ -1994,7 +1994,8 @@
                     }
                     
                     mWakeLockState = mLocks.reactivateScreenLocksLocked();
-                    setPowerState(mUserState | mWakeLockState, noChangeLights, true);
+                    setPowerState(mUserState | mWakeLockState, noChangeLights,
+                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
                     setTimeoutLocked(time, SCREEN_BRIGHT);
                 }
             }
@@ -2125,7 +2126,7 @@
     {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
         synchronized (mLocks) {
-            goToSleepLocked(time);
+            goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
         }
     }
     
@@ -2143,7 +2144,7 @@
         }
     }
 
-    private void goToSleepLocked(long time) {
+    private void goToSleepLocked(long time, int reason) {
 
         if (mLastEventTime <= time) {
             mLastEventTime = time;
@@ -2161,7 +2162,7 @@
             EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
             mStillNeedSleepNotification = true;
             mUserState = SCREEN_OFF;
-            setPowerState(SCREEN_OFF, false, true);
+            setPowerState(SCREEN_OFF, false, reason);
             cancelTimerLocked();
         }
     }
@@ -2517,7 +2518,8 @@
             return;
         }
         if (active) {
-            goToSleepLocked(SystemClock.uptimeMillis());
+            goToSleepLocked(SystemClock.uptimeMillis(),
+                    WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
             mProximitySensorActive = true;
         } else {
             // proximity sensor negative events trigger as user activity.
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 1db20df..a103dcb 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.IBinder;
@@ -1277,8 +1278,13 @@
                 ActivityManagerNative.getDefault().resumeAppSwitches();
             } catch (RemoteException e) {
             }
+            int[] pos = new int[2];
+            v.getLocationOnScreen(pos);
+            Intent overlay = new Intent();
+            overlay.setSourceBounds(
+                    new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
             try {
-                mIntent.send();
+                mIntent.send(mContext, 0, overlay);
                 mNotificationCallbacks.onNotificationClick(mPkg, mTag, mId);
             } catch (PendingIntent.CanceledException e) {
                 // the stack trace isn't very helpful here.  Just log the exception message.
diff --git a/telephony/java/com/android/internal/telephony/MccTable.java b/telephony/java/com/android/internal/telephony/MccTable.java
index c4877cb..e25eb7b 100644
--- a/telephony/java/com/android/internal/telephony/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/MccTable.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.Arrays;
@@ -573,34 +574,36 @@
      * @param mccmnc truncated imsi with just the MCC and MNC - MNC assumed to be from 4th to end
      */
     public static void updateMccMncConfiguration(PhoneBase phone, String mccmnc) {
-        int mcc, mnc;
+        if (!TextUtils.isEmpty(mccmnc)) {
+            int mcc, mnc;
 
-        try {
-            mcc = Integer.parseInt(mccmnc.substring(0,3));
-            mnc = Integer.parseInt(mccmnc.substring(3));
-        } catch (NumberFormatException e) {
-            Log.e(LOG_TAG, "Error parsing IMSI");
-            return;
-        }
+            try {
+                mcc = Integer.parseInt(mccmnc.substring(0,3));
+                mnc = Integer.parseInt(mccmnc.substring(3));
+            } catch (NumberFormatException e) {
+                Log.e(LOG_TAG, "Error parsing IMSI");
+                return;
+            }
 
-        Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
+            Log.d(LOG_TAG, "updateMccMncConfiguration: mcc=" + mcc + ", mnc=" + mnc);
 
-        if (mcc != 0) {
-            setTimezoneFromMccIfNeeded(phone, mcc);
-            setLocaleFromMccIfNeeded(phone, mcc);
-            setWifiChannelsFromMccIfNeeded(phone, mcc);
-        }
-        try {
-            Configuration config = ActivityManagerNative.getDefault().getConfiguration();
             if (mcc != 0) {
-                config.mcc = mcc;
+                setTimezoneFromMccIfNeeded(phone, mcc);
+                setLocaleFromMccIfNeeded(phone, mcc);
+                setWifiChannelsFromMccIfNeeded(phone, mcc);
             }
-            if (mnc != 0) {
-                config.mnc = mnc;
+            try {
+                Configuration config = ActivityManagerNative.getDefault().getConfiguration();
+                if (mcc != 0) {
+                    config.mcc = mcc;
+                }
+                if (mnc != 0) {
+                    config.mnc = mnc;
+                }
+                ActivityManagerNative.getDefault().updateConfiguration(config);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can't update configuration", e);
             }
-            ActivityManagerNative.getDefault().updateConfiguration(config);
-        } catch (RemoteException e) {
-            Log.e(LOG_TAG, "Can't update configuration", e);
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index e47f799..279f57f 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -2191,6 +2191,7 @@
             case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
             case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
             case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;
+            case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break;
             default:
                 throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 99709406..a636a4b 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -109,6 +109,7 @@
         String mimeType = pduDecoder.getValueString();
         if (mimeType == null) {
             binaryContentType = (int)pduDecoder.getValue32();
+            // TODO we should have more generic way to map binaryContentType code to mimeType.
             switch (binaryContentType) {
                 case WspTypeDecoder.CONTENT_TYPE_B_DRM_RIGHTS_XML:
                     mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML;
@@ -128,6 +129,9 @@
                 case WspTypeDecoder.CONTENT_TYPE_B_MMS:
                     mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS;
                     break;
+                case WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF:
+                    mimeType = WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF;
+                    break;
                 default:
                     if (Config.LOGD) {
                         Log.w(LOG_TAG,
@@ -148,6 +152,8 @@
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO;
             } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS)) {
                 binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_MMS;
+            } else if (mimeType.equals(WspTypeDecoder.CONTENT_MIME_TYPE_B_VND_DOCOMO_PF)) {
+                binaryContentType = WspTypeDecoder.CONTENT_TYPE_B_VND_DOCOMO_PF;
             } else {
                 if (Config.LOGD) Log.w(LOG_TAG, "Received PDU. Unknown Content-Type = " + mimeType);
                 return Intents.RESULT_SMS_HANDLED;
@@ -155,28 +161,31 @@
         }
         index += pduDecoder.getDecodedDataLength();
 
-        int dataIndex = headerStartIndex + headerLength;
         boolean dispatchedByApplication = false;
         switch (binaryContentType) {
             case WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO:
-                dispatchWapPdu_PushCO(pdu, transactionId, pduType);
+                dispatchWapPdu_PushCO(pdu, transactionId, pduType, headerStartIndex, headerLength);
                 dispatchedByApplication = true;
                 break;
             case WspTypeDecoder.CONTENT_TYPE_B_MMS:
-                dispatchWapPdu_MMS(pdu, transactionId, pduType, dataIndex);
+                dispatchWapPdu_MMS(pdu, transactionId, pduType, headerStartIndex, headerLength);
                 dispatchedByApplication = true;
                 break;
             default:
                 break;
         }
         if (dispatchedByApplication == false) {
-            dispatchWapPdu_default(pdu, transactionId, pduType, mimeType, dataIndex);
+            dispatchWapPdu_default(pdu, transactionId, pduType, mimeType,
+                                   headerStartIndex, headerLength);
         }
         return Activity.RESULT_OK;
     }
 
-    private void dispatchWapPdu_default(
-            byte[] pdu, int transactionId, int pduType, String mimeType, int dataIndex) {
+    private void dispatchWapPdu_default(byte[] pdu, int transactionId, int pduType,
+                                        String mimeType, int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+        int dataIndex = headerStartIndex + headerLength;
         byte[] data;
 
         data = new byte[pdu.length - dataIndex];
@@ -186,31 +195,40 @@
         intent.setType(mimeType);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", data);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
-    private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) {
+    private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType,
+                                       int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+
         Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
         intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_PUSH_CO);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", pdu);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
-    private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) {
-        byte[] data;
-
-        data = new byte[pdu.length - dataIndex];
+    private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType,
+                                    int headerStartIndex, int headerLength) {
+        byte[] header = new byte[headerLength];
+        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
+        int dataIndex = headerStartIndex + headerLength;
+        byte[] data = new byte[pdu.length - dataIndex];
         System.arraycopy(pdu, dataIndex, data, 0, data.length);
 
         Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);
         intent.setType(WspTypeDecoder.CONTENT_MIME_TYPE_B_MMS);
         intent.putExtra("transactionId", transactionId);
         intent.putExtra("pduType", pduType);
+        intent.putExtra("header", header);
         intent.putExtra("data", data);
 
         mSmsDispatcher.dispatch(intent, "android.permission.RECEIVE_MMS");
diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
index 3bbe0e1..336bc82 100644
--- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
+++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java
@@ -30,12 +30,16 @@
     public static final int PDU_TYPE_PUSH = 0x06;
     public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07;
 
+    // TODO we should have mapping between those binary code and mime type string.
+    //  see http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
+
     public static final int CONTENT_TYPE_B_DRM_RIGHTS_XML = 0x4a;
     public static final int CONTENT_TYPE_B_DRM_RIGHTS_WBXML = 0x4b;
     public static final int CONTENT_TYPE_B_PUSH_SI = 0x2e;
     public static final int CONTENT_TYPE_B_PUSH_SL = 0x30;
     public static final int CONTENT_TYPE_B_PUSH_CO = 0x32;
     public static final int CONTENT_TYPE_B_MMS = 0x3e;
+    public static final int CONTENT_TYPE_B_VND_DOCOMO_PF = 0x0310;
 
     public static final String CONTENT_MIME_TYPE_B_DRM_RIGHTS_XML =
             "application/vnd.oma.drm.rights+xml";
@@ -45,6 +49,7 @@
     public static final String CONTENT_MIME_TYPE_B_PUSH_SL = "application/vnd.wap.slc";
     public static final String CONTENT_MIME_TYPE_B_PUSH_CO = "application/vnd.wap.coc";
     public static final String CONTENT_MIME_TYPE_B_MMS = "application/vnd.wap.mms-message";
+    public static final String CONTENT_MIME_TYPE_B_VND_DOCOMO_PF = "application/vnd.docomo.pf";
 
     public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 04a03b2..422cc19 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -202,10 +202,6 @@
         // Sets current entry in the telephony carrier table
         updateCurrentCarrierInProvider(operatorNumeric);
 
-        // Updates MCC MNC device configuration information
-        MccTable.updateMccMncConfiguration(this, operatorNumeric);
-
-
         // Notify voicemails.
         notifier.notifyMessageWaitingChanged(this);
     }
@@ -1401,20 +1397,22 @@
     }
 
     /**
-     * Sets the "current" field in the telephony provider according to the build-time
-     * operator numeric property
+     * Sets the "current" field in the telephony provider according to the
+     * build-time operator numeric property
      *
      * @return true for success; false otherwise.
      */
-    // TODO(Moto): move this method into PhoneBase, since it looks identical to
-    // the one in GsmPhone
-    private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
+    boolean updateCurrentCarrierInProvider(String operatorNumeric) {
         if (!TextUtils.isEmpty(operatorNumeric)) {
             try {
                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
                 ContentValues map = new ContentValues();
                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
                 getContext().getContentResolver().insert(uri, map);
+
+                // Updates MCC MNC device configuration information
+                MccTable.updateMccMncConfiguration(this, operatorNumeric);
+
                 return true;
             } catch (SQLException e) {
                 Log.e(LOG_TAG, "Can't store current operator", e);
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 7dd4a88..8b8fb38 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -20,7 +20,7 @@
 
 def main(options, args):
   """Run the tests. Will call sys.exit when complete.
-  
+
   """
 
   # Set up logging format.
@@ -56,7 +56,15 @@
   run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
 
   # Call LoadTestsAutoTest::runTest.
-  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix
+  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms
+
+  if options.drawtime:
+    run_load_test_cmd += " -e drawtime true "
+
+  if options.save_image:
+    run_load_test_cmd += " -e saveimage \"%s\"" % options.save_image
+
+  run_load_test_cmd += run_load_test_cmd_postfix
 
   (adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
   fail_flag = False
@@ -101,18 +109,26 @@
 
 if '__main__' == __name__:
   option_parser = optparse.OptionParser()
-  option_parser.add_option("", "--time-out-ms",
+  option_parser.add_option("-t", "--time-out-ms",
                            default=None,
                            help="set the timeout for each test")
-  option_parser.add_option("", "--verbose", action="store_true",
+  option_parser.add_option("-v", "--verbose", action="store_true",
                            default=False,
                            help="include debug-level logging")
-  option_parser.add_option("", "--adb-options",
+  option_parser.add_option("-a", "--adb-options",
                            default=None,
                            help="pass options to adb, such as -d -e, etc");
-  option_parser.add_option("", "--results-directory",
+  option_parser.add_option("-r", "--results-directory",
                            default="layout-test-results",
                            help="directory which results are stored.")
 
+  option_parser.add_option("-d", "--drawtime", action="store_true",
+                           default=False,
+                           help="log draw time for each page rendered.")
+
+  option_parser.add_option("-s", "--save-image",
+                           default=None,
+                           help="stores rendered page to a location on device.")
+
   options, args = option_parser.parse_args();
   main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index fea366c..1a265e8 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -25,6 +25,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.util.regex.Pattern;
 
@@ -156,4 +157,43 @@
         return same;
     }
 
+    public static boolean isTestPageUrl(String url) {
+        int qmPostion = url.indexOf('?');
+        int slashPostion = url.lastIndexOf('/');
+        if (slashPostion < qmPostion) {
+            String fileName = url.substring(slashPostion + 1, qmPostion);
+            if ("index.html".equals(fileName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static String getLastSegmentInPath(String path) {
+        int endPos = path.lastIndexOf('/');
+        path = path.substring(0, endPos);
+        endPos = path.lastIndexOf('/');
+        return path.substring(endPos + 1);
+    }
+
+    public static void writeDrawTime(String fileName, String url, long[] times) {
+        StringBuffer lineBuffer = new StringBuffer();
+        // grab the last segment of path in url
+        lineBuffer.append(getLastSegmentInPath(url));
+        for (long time : times) {
+            lineBuffer.append('\t');
+            lineBuffer.append(time);
+        }
+        lineBuffer.append('\n');
+        String line = lineBuffer.toString();
+        Log.v(LOGTAG, "logging draw times: " + line);
+        try {
+            FileWriter fw = new FileWriter(fileName, true);
+            fw.write(line);
+            fw.close();
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "Failed to log draw times", ioe);
+        }
+    }
+
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index 283b98c..539d551 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -73,13 +73,20 @@
         this.mLogtime = (logtime != null
                 && logtime.toLowerCase().equals("true"));
 
+        String drawTime = (String) icicle.get("drawtime");
+        this.mGetDrawTime = (drawTime != null
+                && drawTime.toLowerCase().equals("true"));
+
+        mSaveImagePath = (String) icicle.get("saveimage");
+
         super.onCreate(icicle);
     }
     
     public String mTestPath = null;
+    public String mSaveImagePath = null;
     public int mTimeoutInMillis = 0;
     public int mDelay = 0;
     public boolean mRebaseline = false;
     public boolean mLogtime = false;
+    public boolean mGetDrawTime = false;
 }
-
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index ba46197..2ef342f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -70,7 +70,8 @@
         freeMem();
 
         // Run tests
-        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
+        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis,
+                runner.mGetDrawTime, runner.mSaveImagePath);
 
         activity.clearCache();
         try {
@@ -161,7 +162,8 @@
     }
 
     // A convenient method to be called by another activity.
-    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout) {
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout,
+            boolean getDrawTime, String saveImagePath) {
         activity.setCallback(new TestShellCallback() {
             public void finished() {
                 synchronized (LoadTestsAutoTest.this) {
@@ -181,6 +183,9 @@
         intent.putExtra(TestShellActivity.TEST_URL, url);
         intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
         intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT);
+        intent.putExtra(TestShellActivity.GET_DRAW_TIME, getDrawTime);
+        if (saveImagePath != null)
+            intent.putExtra(TestShellActivity.SAVE_IMAGE, saveImagePath);
         activity.startActivity(intent);
 
         // Wait until done.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index aeb55b4..b6b1661 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -25,6 +25,9 @@
 import android.content.Intent;
 import android.content.DialogInterface.OnClickListener;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Bitmap.Config;
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Handler;
@@ -163,6 +166,8 @@
 
         mResultFile = intent.getStringExtra(RESULT_FILE);
         mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
+        mGetDrawtime = intent.getBooleanExtra(GET_DRAW_TIME, false);
+        mSaveImagePath = intent.getStringExtra(SAVE_IMAGE);
 
         Log.v(LOGTAG, "  Loading " + mTestUrl);
         mWebView.loadUrl(mTestUrl);
@@ -459,6 +464,18 @@
         public void onPageFinished(WebView view, String url) {
             Log.v(LOGTAG, "onPageFinished, url=" + url);
             mPageFinished = true;
+            // get page draw time
+            if (FsUtils.isTestPageUrl(url)) {
+                if (mGetDrawtime) {
+                    long[] times = new long[DRAW_RUNS];
+                    times = getDrawWebViewTime(mWebView, DRAW_RUNS);
+                    FsUtils.writeDrawTime(DRAW_TIME_LOG, url, times);
+                }
+                if (mSaveImagePath != null) {
+                    String name = FsUtils.getLastSegmentInPath(url);
+                    drawPageToFile(mSaveImagePath + "/" + name + ".png", mWebView);
+                }
+            }
             // Calling finished() will check if we've met all the conditions for completing
             // this test and move to the next one if we are ready.
             if (finished()) {
@@ -691,6 +708,41 @@
         mPageFinished = false;
         mOneHundredPercentComplete = false;
         mDumpWebKitData = false;
+        mGetDrawtime = false;
+        mSaveImagePath = null;
+    }
+
+    private long[] getDrawWebViewTime(WebView view, int count) {
+        if (count == 0)
+            return null;
+        long[] ret = new long[count];
+        long start;
+        Canvas canvas = new Canvas();
+        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
+        canvas.setBitmap(bitmap);
+        for (int i = 0; i < count; i++) {
+            start = System.currentTimeMillis();
+            view.draw(canvas);
+            ret[i] = System.currentTimeMillis() - start;
+        }
+        return ret;
+    }
+
+    private void drawPageToFile(String fileName, WebView view) {
+        Canvas canvas = new Canvas();
+        Bitmap bitmap = Bitmap.createBitmap(view.getContentWidth(), view.getContentHeight(),
+                Config.ARGB_8888);
+        canvas.setBitmap(bitmap);
+        view.drawPage(canvas);
+        try {
+            FileOutputStream fos = new FileOutputStream(fileName);
+            if(!bitmap.compress(CompressFormat.PNG, 90, fos)) {
+                Log.w(LOGTAG, "Failed to compress and save image.");
+            }
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "", ioe);
+        }
+        bitmap.recycle();
     }
 
     private boolean canMoveToNextTest() {
@@ -730,7 +782,9 @@
     private String mResultFile;
     private int mTimeoutInMillis;
     private String mUiAutoTestPath;
+    private String mSaveImagePath;
     private BufferedReader mTestListReader;
+    private boolean mGetDrawtime;
 
     // States
     private boolean mTimedOut;
@@ -766,6 +820,11 @@
     static final String RESULT_FILE = "ResultFile";
     static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
     static final String UI_AUTO_TEST = "UiAutoTest";
+    static final String GET_DRAW_TIME = "GetDrawTime";
+    static final String SAVE_IMAGE = "SaveImage";
+
+    static final int DRAW_RUNS = 5;
+    static final String DRAW_TIME_LOG = "/sdcard/android/page_draw_time.txt";
 
     private boolean mGeolocationPermissionSet;
     private boolean mGeolocationPermission;
diff --git a/tests/backup/test_backup.sh b/tests/backup/test_backup.sh
index 10b809d..113a26d 100755
--- a/tests/backup/test_backup.sh
+++ b/tests/backup/test_backup.sh
@@ -18,10 +18,12 @@
 #export DRY_RUN="echo"
 source test_backup_common.sh
 
-# wipe prior backup data for packages
+# figure out what packages are participating in backup
 b_pkgs=$(a shell dumpsys backup | \
-         ruby -ne 'print($1+" ") if $_ =~ /^\s*ApplicationInfo\S+ (.+?)\}/')
+         ruby -e 'p_stanza = STDIN.read.match(/Participants:.*?(?=Ever)/m)[0]
+                  puts p_stanza.scan(/^    (.+?)\s*$/).flatten.join(" ")')
 
+# wipe data for the package participating in backup
 for pkg in $b_pkgs; do
     a shell bmgr wipe "$pkg"
 done
@@ -36,7 +38,7 @@
 set -x
 
 # set the transport
-a shell bmgr transport com.google.android.backup/.BackupTransportService
+#a shell bmgr transport com.google.android.backup/.BackupTransportService
 
 # load up the three files
 a shell \
diff --git a/tests/backup/test_restore.sh b/tests/backup/test_restore.sh
index 46b46e4..48e5c66 100755
--- a/tests/backup/test_restore.sh
+++ b/tests/backup/test_restore.sh
@@ -45,7 +45,7 @@
     fi
 }
 
-# run adb as root so we can poke at com.android.backuptest's data
+# Make sure adb is root so we can poke at com.android.backuptest's data
 adb_root
 
 # delete the old data