Merge change 25175 into eclair

* changes:
  Allow only System Service to send most Bluetooth intents.
diff --git a/api/current.xml b/api/current.xml
index 38490f3..6121c43 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6825,7 +6825,7 @@
  value="16843221"
  static="true"
  final="true"
- deprecated="deprecated"
+ deprecated="not deprecated"
  visibility="public"
 >
 </field>
@@ -150079,6 +150079,19 @@
  visibility="public"
 >
 </method>
+<method name="setOnTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onTop" type="boolean">
+</parameter>
+</method>
 </class>
 <class name="TouchDelegate"
  extends="java.lang.Object"
@@ -167425,24 +167438,13 @@
 </parameter>
 </method>
 </class>
-<class name="PluginStub"
- extends="java.lang.Object"
+<interface name="PluginStub"
  abstract="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="PluginStub"
- type="android.webkit.PluginStub"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="npp" type="int">
-</parameter>
-</constructor>
 <method name="getEmbeddedView"
  return="android.view.View"
  abstract="true"
@@ -167453,6 +167455,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="NPP" type="int">
+</parameter>
 <parameter name="context" type="android.content.Context">
 </parameter>
 </method>
@@ -167466,10 +167470,12 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="NPP" type="int">
+</parameter>
 <parameter name="context" type="android.content.Context">
 </parameter>
 </method>
-</class>
+</interface>
 <class name="SslErrorHandler"
  extends="android.os.Handler"
  abstract="false"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 39ed769..5b55252 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -11,6 +11,7 @@
 	libstagefright
 
 LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
 	frameworks/base/media/libstagefright \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
 
@@ -32,6 +33,7 @@
 	libstagefright
 
 LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
 	frameworks/base/media/libstagefright \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
 
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 6abed93..c13893a 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1445,13 +1445,18 @@
                             intent.getComponent().getClassName())) {
                 createNoCredentialsPermissionNotification(account, intent);
             } else {
+                final Integer notificationId = getSigninRequiredNotificationId(account);
+                intent.addCategory(String.valueOf(notificationId));
                 Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
                         0 /* when */);
-                n.setLatestEventInfo(mContext, mContext.getText(R.string.notification_title),
+                final String notificationTitleFormat =
+                        mContext.getText(R.string.notification_title).toString();
+                n.setLatestEventInfo(mContext,
+                        String.format(notificationTitleFormat, account.name),
                         message, PendingIntent.getActivity(
                         mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
                 ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                        .notify(getSigninRequiredNotificationId(account), n);
+                        .notify(notificationId, n);
             }
         } finally {
             restoreCallingIdentity(identityToken);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0cd4036..e425f3a 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -22,10 +22,11 @@
 import android.database.SQLException;
 import android.os.Debug;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Config;
-import android.util.Log;
 import android.util.EventLog;
+import android.util.Log;
 
 import java.io.File;
 import java.util.HashMap;
@@ -221,6 +222,10 @@
     // that logging is not enabled.
     /* package */ final boolean mLogStats;
 
+    // System property that enables logging of slow queries. Specify the threshold in ms.
+    private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
+    private final int mSlowQueryThreshold;
+
     /**
      * @param closable
      */
@@ -1202,27 +1207,38 @@
             String editTable) {
         long timeStart = 0;
 
-        if (Config.LOGV) {
+        if (Config.LOGV || mSlowQueryThreshold != -1) {
             timeStart = System.currentTimeMillis();
         }
 
         SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable);
 
+        Cursor cursor = null;
         try {
-            return driver.query(
+            cursor = driver.query(
                     cursorFactory != null ? cursorFactory : mFactory,
                     selectionArgs);
         } finally {
-            if (Config.LOGV) {
+            if (Config.LOGV || mSlowQueryThreshold != -1) {
+
+                // Force query execution
+                if (cursor != null) {
+                    cursor.moveToFirst();
+                    cursor.moveToPosition(-1);
+                }
+
                 long duration = System.currentTimeMillis() - timeStart;
 
-                Log.v(SQLiteCursor.TAG,
-                      "query (" + duration + " ms): " + driver.toString() + ", args are "
-                              + (selectionArgs != null
-                              ? TextUtils.join(",", selectionArgs)
-                              : "<null>"));
+                if (Config.LOGV || duration >= mSlowQueryThreshold) {
+                    Log.v(SQLiteCursor.TAG,
+                          "query (" + duration + " ms): " + driver.toString() + ", args are "
+                                  + (selectionArgs != null
+                                  ? TextUtils.join(",", selectionArgs)
+                                  : "<null>"));
+                }
             }
         }
+        return cursor;
     }
 
     /**
@@ -1671,6 +1687,7 @@
         mFlags = flags;
         mPath = path;
         mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
+        mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
 
         mLeakedException = new IllegalStateException(path +
             " SQLiteDatabase created and never closed");
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
index a6ef6473..594c0e8 100755
--- a/core/java/android/os/IHardwareService.aidl
+++ b/core/java/android/os/IHardwareService.aidl
@@ -28,12 +28,6 @@
     boolean getFlashlightEnabled();
     void setFlashlightEnabled(boolean on);
     void enableCameraFlash(int milliseconds);
-    
-    // sets the brightness of the backlights (screen, keyboard, button) 0-255
-    void setBacklights(int brightness);
-
-    // enables or disables automatic brightness mode
-    void setAutoBrightness(boolean on);
 
     // for the phone
     void setAttentionLight(boolean on);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 188e7ff..189335e 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -31,4 +31,10 @@
     long getScreenOnTime();
     void preventScreenOn(boolean prevent);
     void setScreenBrightnessOverride(int brightness);
+
+    // sets the brightness of the backlights (screen, keyboard, button) 0-255
+    void setBacklightBrightness(int brightness);
+
+    // enables or disables automatic brightness mode
+    void setAutoBrightness(boolean on);
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d5934102..11c96d2 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -379,6 +379,21 @@
         }
     }
 
+    /**
+     * sets the brightness of the backlights (screen, keyboard, button).
+     *
+     * @param brightness value from 0 to 255
+     *
+     * {@hide}
+     */
+    public void setBacklightBrightness(int brightness)
+    {
+        try {
+            mService.setBacklightBrightness(brightness);
+        } catch (RemoteException e) {
+        }
+    }
+
    /**
      * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
      * that are supported on the device.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d354ccf..b0ac7f4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -46,6 +46,15 @@
     /** A content:// style uri to the authority for the contacts provider */
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
+    /**
+     * An optional insert, update or delete URI parameter that allows the caller
+     * to specify that it is a sync adapter. The default value is false. If true
+     * the dirty flag is not automatically set and the "syncToNetwork" parameter
+     * is set to false when calling
+     * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
+     */
+    public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+
     public interface SyncStateColumns extends SyncStateContract.Columns {
     }
 
@@ -480,7 +489,8 @@
          * called on a raw contact, it is marked for deletion and removed from its
          * aggregate contact. The sync adaptor deletes the raw contact on the server and
          * then calls ContactResolver.delete once more, this time passing the
-         * {@link RawContacts#DELETE_PERMANENTLY} query parameter to finalize the data removal.
+         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+         * the data removal.
          * <P>Type: INTEGER</P>
          */
         public static final String DELETED = "deleted";
@@ -517,14 +527,6 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
 
         /**
-         * Query parameter that can be passed with the {@link #CONTENT_URI} URI
-         * to the {@link android.content.ContentResolver#delete} method to
-         * indicate that the raw contact can be deleted physically, rather than
-         * merely marked as deleted.
-         */
-        public static final String DELETE_PERMANENTLY = "delete_permanently";
-
-        /**
          * Aggregation mode: aggregate asynchronously.
          */
         public static final int AGGREGATION_MODE_DEFAULT = 0;
@@ -648,13 +650,6 @@
         public static final String SYNC3 = "data_sync3";
         /** Generic column for use by sync adapters. */
         public static final String SYNC4 = "data_sync4";
-
-        /**
-         * An optional insert, update or delete URI parameter that determines if
-         * the corresponding raw contact should be marked as dirty. The default
-         * value is true.
-         */
-        public static final String MARK_AS_DIRTY = "mark_as_dirty";
     }
 
     /**
@@ -1533,8 +1528,9 @@
          * for deletion. When {@link android.content.ContentResolver#delete} is
          * called on a raw contact, it is marked for deletion and removed from its
          * aggregate contact. The sync adaptor deletes the raw contact on the server and
-         * then calls ContactResolver.delete once more, this time passing the
-         * {@link RawContacts#DELETE_PERMANENTLY} query parameter to finalize the data removal.
+         * then calls ContactResolver.delete once more, this time setting the the
+         * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize 
+         * the data removal.
          * <P>Type: INTEGER</P>
          */
         public static final String DELETED = "deleted";
@@ -1579,20 +1575,6 @@
          * The MIME type of a single group.
          */
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group";
-
-        /**
-         * Query parameter that can be passed with the {@link #CONTENT_URI} URI
-         * to the {@link android.content.ContentResolver#delete} method to
-         * indicate that the raw contact can be deleted physically, rather than
-         * merely marked as deleted.
-         */
-        public static final String DELETE_PERMANENTLY = "delete_permanently";
-
-        /**
-         * An optional update or insert URI parameter that determines if the
-         * group should be marked as dirty. The default value is true.
-         */
-        public static final String MARK_AS_DIRTY = "mark_as_dirty";
     }
 
     /**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index a6d76d6..3f369dd 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -35,9 +35,13 @@
 /**
  *
  * Synthesizes speech from text for immediate playback or to create a sound file.
+ * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its
+ * initialization. Implement the {@link TextToSpeech.OnInitListener} to be
+ * notified of the completion of the initialization.<br>
+ * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method
+ * to release the native resources used by the TextToSpeech engine.
  *
  */
-//TODO complete javadoc + add links to constants
 public class TextToSpeech {
 
     /**
@@ -85,7 +89,7 @@
     public static final int LANG_MISSING_DATA = -1;
 
     /**
-     * Denotes the language is not supported by the current TTS engine.
+     * Denotes the language is not supported.
      */
     public static final int LANG_NOT_SUPPORTED = -2;
 
@@ -100,29 +104,38 @@
 
 
     /**
-     * Called when the TTS has initialized.
-     *
-     * The InitListener must implement the onInit function. onInit is passed a
-     * status code indicating the result of the TTS initialization.
+     * Interface definition of a callback to be invoked indicating the completion of the
+     * TextToSpeech engine initialization.
      */
     public interface OnInitListener {
+        /**
+         * Called to signal the completion of the TextToSpeech engine initialization.
+         * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
+         */
         public void onInit(int status);
     }
 
     /**
-     * Called when the TTS has completed saying something that has an utterance ID set.
+     * Interface definition of a callback to be invoked indicating the TextToSpeech engine has
+     * completed synthesizing an utterance with an utterance ID set.
      *
-     * The OnUtteranceCompletedListener must implement the onUtteranceCompleted function.
-     * onUtteranceCompleted is passed a String that is the utteranceId given in
-     * the original speak call.
      */
-    public interface OnUtteranceCompletedListener {

+    public interface OnUtteranceCompletedListener {
+        /**
+         * Called to signal the completion of the synthesis of the utterance that was identified
+         * with the string parameter. This identifier is the one originally passed in the
+         * parameter hashmap of the synthesis request in
+         * {@link TextToSpeech#speak(String, int, HashMap)} or
+         * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the
+         * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key.
+         * @param utteranceId the identifier of the utterance.
+         */

         public void onUtteranceCompleted(String utteranceId);

     }
 
 
     /**
-     * Internal constants for the TTS functionality
+     * Internal constants for the TextToSpeech functionality
      *
      */
     public class Engine {
@@ -145,38 +158,41 @@
         public static final String DEFAULT_SYNTH = "com.svox.pico";
 
         // default values for rendering
+        /**
+         * Default audio stream used when playing synthesized speech.
+         */
         public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
 
         // return codes for a TTS engine's check data activity
         /**
          * Indicates success when checking the installation status of the resources used by the
-         * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+         * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
          */
         public static final int CHECK_VOICE_DATA_PASS = 1;
         /**
          * Indicates failure when checking the installation status of the resources used by the
-         * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+         * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
          */
         public static final int CHECK_VOICE_DATA_FAIL = 0;
         /**
          * Indicates erroneous data when checking the installation status of the resources used by
-         * the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+         * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
          */
         public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
         /**
          * Indicates missing resources when checking the installation status of the resources used
-         * by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+         * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
          */
         public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
         /**
          * Indicates missing storage volume when checking the installation status of the resources
-         * used by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
+         * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
          */
         public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3;
 
         // intents to ask engine to install data or check its data
         /**
-         * Activity Action: Triggers the platform Text-To-Speech engine to
+         * Activity Action: Triggers the platform TextToSpeech engine to
          * start the activity that installs the resource files on the device
          * that are required for TTS to be operational. Since the installation
          * of the data can be interrupted or declined by the user, the application
@@ -197,7 +213,7 @@
         public static final String ACTION_TTS_DATA_INSTALLED =
                 "android.speech.tts.engine.TTS_DATA_INSTALLED";
         /**
-         * Activity Action: Starts the activity from the platform Text-To-Speech
+         * Activity Action: Starts the activity from the platform TextToSpeech
          * engine to verify the proper installation and availability of the
          * resource files on the system. Upon completion, the activity will
          * return one of the following codes:
@@ -210,9 +226,9 @@
          * fields:
          * <ul>
          *   <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which
-         *       indicates the path to the location of the resource files</li>,
+         *       indicates the path to the location of the resource files,</li>
          *   <li>{@link #EXTRA_VOICE_DATA_FILES} which contains
-         *       the list of all the resource files</li>,
+         *       the list of all the resource files,</li>
          *   <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which
          *       contains, for each resource file, the description of the language covered by
          *       the file in the xxx-YYY format, where xxx is the 3-letter ISO language code,
@@ -226,18 +242,18 @@
         // extras for a TTS engine's check data activity
         /**
          * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
-         * the text-to-speech engine specifies the path to its resources.
+         * the TextToSpeech engine specifies the path to its resources.
          */
         public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
         /**
          * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
-         * the text-to-speech engine specifies the file names of its resources under the
+         * the TextToSpeech engine specifies the file names of its resources under the
          * resource path.
          */
         public static final String EXTRA_VOICE_DATA_FILES = "dataFiles";
         /**
          * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
-         * the text-to-speech engine specifies the locale associated with each resource file.
+         * the TextToSpeech engine specifies the locale associated with each resource file.
          */
         public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
 
@@ -272,11 +288,17 @@
         /**
          * Parameter key to specify the audio stream type to be used when speaking text
          * or playing back a file.
+         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#playEarcon(String, int, HashMap)
          */
         public static final String KEY_PARAM_STREAM = "streamType";
         /**
-         * Parameter key to identify an utterance in the completion listener after text has been
+         * Parameter key to identify an utterance in the
+         * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been
          * spoken, a file has been played back or a silence duration has elapsed.
+         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#playEarcon(String, int, HashMap)
+         * @see TextToSpeech#synthesizeToFile(String, HashMap, String)
          */
         public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId";
 
@@ -330,13 +352,14 @@
     private String[] mCachedParams;
 
     /**
-     * The constructor for the TTS.
+     * The constructor for the TextToSpeech class.
+     * This will also initialize the associated TextToSpeech engine if it isn't already running.
      *
      * @param context
-     *            The context
+     *            The context this instance is running in.
      * @param listener
-     *            The InitListener that will be called when the TTS has
-     *            initialized successfully.
+     *            The {@link TextToSpeech.OnInitListener} that will be called when the
+     *            TextToSpeech engine has initialized.
      */
     public TextToSpeech(Context context, OnInitListener listener) {
         mContext = context;
@@ -402,9 +425,9 @@
 
 
     /**
-     * Shuts down the TTS. It is good practice to call this in the onDestroy
-     * method of the Activity that is using the TTS so that the TTS is stopped
-     * cleanly.
+     * Releases the resources used by the TextToSpeech engine.
+     * It is good practice for instance to call this method in the onDestroy() method of an Activity
+     * so the TextToSpeech engine can be cleanly stopped.
      */
     public void shutdown() {
         try {
@@ -418,11 +441,12 @@
 
     /**
      * Adds a mapping between a string of text and a sound resource in a
-     * package.
-     * @see #speak(String, int, HashMap)
+     * package. After a call to this method, subsequent calls to
+     * {@link #speak(String, int, HashMap)} will play the specified sound resource
+     * if it is available, or synthesize the text it is missing.
      *
      * @param text
-     *            Example: <b><code>"south_south_east"</code></b><br/>
+     *            The string of text. Example: <code>"south_south_east"</code>
      *
      * @param packagename
      *            Pass the packagename of the application that contains the
@@ -438,7 +462,7 @@
      *            </p>
      *
      * @param resourceId
-     *            Example: <b><code>R.raw.south_south_east</code></b>
+     *            Example: <code>R.raw.south_south_east</code>
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -476,10 +500,13 @@
 
     /**
      * Adds a mapping between a string of text and a sound file. Using this, it
-     * is possible to add custom pronounciations for text.
+     * is possible to add custom pronounciations for a string of text.
+     * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)}
+     * will play the specified sound resource if it is available, or synthesize the text it is
+     * missing.
      *
      * @param text
-     *            The string of text
+     *            The string of text. Example: <code>"south_south_east"</code>
      * @param filename
      *            The full path to the sound file (for example:
      *            "/sdcard/mysounds/hello.wav")
@@ -520,28 +547,26 @@
 
     /**
      * Adds a mapping between a string of text and a sound resource in a
-     * package.
+     * package. Use this to add custom earcons.
      *
      * @see #playEarcon(String, int, HashMap)
      *
-     * @param earcon The name of the earcon
-     *            Example: <b><code>"[tick]"</code></b><br/>
+     * @param earcon The name of the earcon.
+     *            Example: <code>"[tick]"</code><br/>
      *
      * @param packagename
-     *            Pass the packagename of the application that contains the
-     *            resource. If the resource is in your own application (this is
-     *            the most common case), then put the packagename of your
-     *            application here.<br/>
+     *            the package name of the application that contains the
+     *            resource. This can for instance be the package name of your own application.
      *            Example: <b>"com.google.marvin.compass"</b><br/>
-     *            The packagename can be found in the AndroidManifest.xml of
-     *            your application.
+     *            The package name can be found in the AndroidManifest.xml of
+     *            the application containing the resource.
      *            <p>
      *            <code>&lt;manifest xmlns:android=&quot;...&quot;
      *      package=&quot;<b>com.google.marvin.compass</b>&quot;&gt;</code>
      *            </p>
      *
      * @param resourceId
-     *            Example: <b><code>R.raw.tick_snd</code></b>
+     *            Example: <code>R.raw.tick_snd</code>
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -578,11 +603,14 @@
 
 
     /**
-     * Adds a mapping between a string of text and a sound file. Using this, it
-     * is possible to add custom earcons.
+     * Adds a mapping between a string of text and a sound file.
+     * Use this to add custom earcons.
+     *
+     * @see #playEarcon(String, int, HashMap)
      *
      * @param earcon
-     *            The name of the earcon
+     *            The name of the earcon.
+     *            Example: <code>"[tick]"</code>
      * @param filename
      *            The full path to the sound file (for example:
      *            "/sdcard/mysounds/tick.wav")
@@ -623,18 +651,18 @@
 
     /**
      * Speaks the string using the specified queuing strategy and speech
-     * parameters. Note that the speech parameters are not universally supported
-     * by all engines and will be treated as a hint. The TTS library will try to
-     * fulfill these parameters as much as possible, but there is no guarantee
-     * that the voice used will have the properties specified.
+     * parameters.
      *
      * @param text
      *            The string of text to be spoken.
      * @param queueMode
      *            The queuing strategy to use.
-     *            See QUEUE_ADD and QUEUE_FLUSH.
+     *            {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
      * @param params
-     *            The hashmap of speech parameters to be used.
+     *            The list of parameters to be used. Can be null if no parameters are given.
+     *            They are specified using a (key, value) pair, where the key can be
+     *            {@link Engine#KEY_PARAM_STREAM} or
+     *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -690,9 +718,12 @@
      * @param earcon
      *            The earcon that should be played
      * @param queueMode
-     *            See QUEUE_ADD and QUEUE_FLUSH.
+     *            {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
      * @param params
-     *            The hashmap of parameters to be used.
+     *            The list of parameters to be used. Can be null if no parameters are given.
+     *            They are specified using a (key, value) pair, where the key can be
+     *            {@link Engine#KEY_PARAM_STREAM} or
+     *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -747,7 +778,11 @@
      * @param durationInMs
      *            A long that indicates how long the silence should last.
      * @param queueMode
-     *            See QUEUE_ADD and QUEUE_FLUSH.
+     *            {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
+     * @param params
+     *            The list of parameters to be used. Can be null if no parameters are given.
+     *            They are specified using a (key, value) pair, where the key can be
+     *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -791,9 +826,9 @@
 
 
     /**
-     * Returns whether or not the TTS is busy speaking.
+     * Returns whether or not the TextToSpeech engine is busy speaking.
      *
-     * @return Whether or not the TTS is busy speaking.
+     * @return Whether or not the TextToSpeech engine is busy speaking.
      */
     public boolean isSpeaking() {
         synchronized (mStartLock) {
@@ -827,7 +862,8 @@
 
 
     /**
-     * Stops speech from the TTS.
+     * Interrupts the current utterance (whether played or rendered to file) and discards other
+     * utterances in the queue.
      *
      * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
      */
@@ -865,15 +901,12 @@
 
 
     /**
-     * Sets the speech rate for the TTS engine.
+     * Sets the speech rate for the TextToSpeech engine.
      *
-     * Note that the speech rate is not universally supported by all engines and
-     * will be treated as a hint. The TTS library will try to use the specified
-     * speech rate, but there is no guarantee.
      * This has no effect on any pre-recorded speech.
      *
      * @param speechRate
-     *            The speech rate for the TTS engine. 1 is the normal speed,
+     *            The speech rate for the TextToSpeech engine. 1 is the normal speed,
      *            lower values slow down the speech (0.5 is half the normal speech rate),
      *            greater values accelerate it (2 is twice the normal speech rate).
      *
@@ -917,15 +950,12 @@
 
 
     /**
-     * Sets the speech pitch for the TTS engine.
+     * Sets the speech pitch for the TextToSpeech engine.
      *
-     * Note that the pitch is not universally supported by all engines and
-     * will be treated as a hint. The TTS library will try to use the specified
-     * pitch, but there is no guarantee.
      * This has no effect on any pre-recorded speech.
      *
      * @param pitch
-     *            The pitch for the TTS engine. 1 is the normal pitch,
+     *            The pitch for the TextToSpeech engine. 1 is the normal pitch,
      *            lower values lower the tone of the synthesized voice,
      *            greater values increase it.
      *
@@ -967,11 +997,11 @@
 
 
     /**
-     * Sets the language for the TTS engine.
-     *
-     * Note that the language is not universally supported by all engines and
-     * will be treated as a hint. The TTS library will try to use the specified
-     * language as represented by the Locale, but there is no guarantee.
+     * Sets the language for the TextToSpeech engine.
+     * The TextToSpeech engine will try to use the closest match to the specified
+     * language as represented by the Locale, but there is no guarantee that the exact same Locale
+     * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support
+     * before choosing the language to use for the next utterances.
      *
      * @param loc
      *            The locale describing the language to be used.
@@ -1023,9 +1053,10 @@
 
 
     /**
-     * Returns a Locale instance describing the language currently being used by the TTS engine.
+     * Returns a Locale instance describing the language currently being used by the TextToSpeech
+     * engine.
      * @return language, country (if any) and variant (if any) used by the engine stored in a Locale
-     *     instance, or null is the TTS engine has failed.
+     *     instance, or null is the TextToSpeech engine has failed.
      */
     public Locale getLanguage() {
         synchronized (mStartLock) {
@@ -1063,7 +1094,7 @@
     }
 
     /**
-     * Checks if the specified language as represented by the Locale is available.
+     * Checks if the specified language as represented by the Locale is available and supported.
      *
      * @param loc
      *            The Locale describing the language to be used.
@@ -1112,7 +1143,9 @@
      * @param text
      *            The String of text that should be synthesized
      * @param params
-     *            A hashmap of parameters.
+     *            The list of parameters to be used. Can be null if no parameters are given.
+     *            They are specified using a (key, value) pair, where the key can be
+     *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
      * @param filename
      *            The string that gives the full output filename; it should be
      *            something like "/sdcard/myappsounds/mysound.wav".
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 172e9ac..38881d3 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -401,16 +401,12 @@
     private static SparseArray<String> PICKER_SETS =
                         new SparseArray<String>();
     static {
-        PICKER_SETS.put('!', "\u00A1");
-        PICKER_SETS.put('<', "\u00AB");
-        PICKER_SETS.put('>', "\u00BB");
-        PICKER_SETS.put('?', "\u00BF");
         PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100");
         PICKER_SETS.put('C', "\u00C7\u0106\u010C");
         PICKER_SETS.put('D', "\u010E");
         PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112");
         PICKER_SETS.put('L', "\u0141");
-        PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A");
+        PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A\u0130");
         PICKER_SETS.put('N', "\u00D1\u0143\u0147");
         PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C");
         PICKER_SETS.put('R', "\u0158");
@@ -423,7 +419,7 @@
         PICKER_SETS.put('c', "\u00E7\u0107\u010D");
         PICKER_SETS.put('d', "\u010F");
         PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113");
-        PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B");
+        PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B\u0131");
         PICKER_SETS.put('l', "\u0142");
         PICKER_SETS.put('n', "\u00F1\u0144\u0148");
         PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D");
@@ -435,6 +431,33 @@
         PICKER_SETS.put('z', "\u017A\u017C\u017E");
         PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
                              "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\");
+
+        // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml
+
+        PICKER_SETS.put('1', "\u00b9\u00bd\u2153\u00bc\u215b");
+        PICKER_SETS.put('2', "\u00b2\u2154");
+        PICKER_SETS.put('3', "\u00b3\u00be\u215c");
+        PICKER_SETS.put('4', "\u2074");
+        PICKER_SETS.put('5', "\u215d");
+        PICKER_SETS.put('7', "\u215e");
+        PICKER_SETS.put('0', "\u207f\u2205");
+        PICKER_SETS.put('$', "\u00a2\u00a3\u20ac\u00a5\u20a3\u20a4\u20b1");
+        PICKER_SETS.put('%', "\u2030");
+        PICKER_SETS.put('*', "\u2020\u2021");
+        PICKER_SETS.put('-', "\u2013\u2014");
+        PICKER_SETS.put('+', "\u00b1");
+        PICKER_SETS.put('(', "[{<");
+        PICKER_SETS.put(')', "]}>");
+        PICKER_SETS.put('!', "\u00a1");
+        PICKER_SETS.put('"', "\u201c\u201d\u00ab\u00bb\u02dd");
+        PICKER_SETS.put('?', "\u00bf");
+        PICKER_SETS.put(',', "\u201a\u201e");
+
+        // From packages/inputmethods/LatinIME/res/xml/kbd_symbols_shift.xml
+
+        PICKER_SETS.put('=', "\u2260\u2248\u221e");
+        PICKER_SETS.put('<', "\u2264\u00ab\u2039");
+        PICKER_SETS.put('>', "\u2265\u00bb\u203a");
     };
 
     private boolean showCharacterPicker(View view, Editable content, char c,
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1426aef..356f55a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -236,6 +236,10 @@
 
     @Override
     public boolean gatherTransparentRegion(Region region) {
+        if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+            return super.gatherTransparentRegion(region);
+        }
+        
         boolean opaque = true;
         if ((mPrivateFlags & SKIP_DRAW) == 0) {
             // this view draws, remove it from the transparent region
@@ -259,20 +263,24 @@
 
     @Override
     public void draw(Canvas canvas) {
-        // draw() is not called when SKIP_DRAW is set
-        if ((mPrivateFlags & SKIP_DRAW) == 0) {
-            // punch a whole in the view-hierarchy below us
-            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+            // draw() is not called when SKIP_DRAW is set
+            if ((mPrivateFlags & SKIP_DRAW) == 0) {
+                // punch a whole in the view-hierarchy below us
+                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+            }
         }
         super.draw(canvas);
     }
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        // if SKIP_DRAW is cleared, draw() has already punched a hole
-        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-            // punch a whole in the view-hierarchy below us
-            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+            // if SKIP_DRAW is cleared, draw() has already punched a hole
+            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                // punch a whole in the view-hierarchy below us
+                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+            }
         }
         // reposition ourselves where the surface is 
         mHaveFrame = true;
@@ -281,6 +289,22 @@
     }
 
     /**
+     * Control whether the surface view's surface is placed on top of its
+     * window.  Normally it is placed behind the window, to allow it to
+     * (for the most part) appear to composite with the views in the
+     * hierarchy.  By setting this, you cause it to be placed above the
+     * window.  This means that none of the contents of the window this
+     * SurfaceView is in will be visible on top of its surface.
+     * 
+     * <p>Note that this must be set before the surface view's containing
+     * window is attached to the window manager.
+     */
+    public void setOnTop(boolean onTop) {
+        mWindowType = onTop ? WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
+                : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+    }
+    
+    /**
      * Hack to allow special layering of windows.  The type is one of the
      * types in WindowManager.LayoutParams.  This is a hack so:
      * @hide
@@ -345,7 +369,9 @@
                 }
                 
                 mLayout.format = mRequestedFormat;
-                mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+                mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                              | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                               | WindowManager.LayoutParams.FLAG_SCALED
                               | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                               | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index db6b74f..465eef8 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -222,7 +222,6 @@
 
     private void resetLoadingStates() {
         mCommitted = true;
-        mWebViewCore.mEndScaleZoom = mFirstLayoutDone == false;
         mFirstLayoutDone = true;
     }
 
@@ -245,7 +244,6 @@
             // blocking the update in {@link #loadStarted}
             mWebViewCore.contentDraw();
         }
-        mWebViewCore.mEndScaleZoom = true;
     }
 
     /**
diff --git a/core/java/android/webkit/PluginActivity.java b/core/java/android/webkit/PluginActivity.java
index f9e3080..cda7b59 100644
--- a/core/java/android/webkit/PluginActivity.java
+++ b/core/java/android/webkit/PluginActivity.java
@@ -49,10 +49,10 @@
         final int npp = intent.getIntExtra(INTENT_EXTRA_NPP_INSTANCE, -1);
         // Retrieve the PluginStub implemented in packageName.className
         PluginStub stub =
-                PluginUtil.getPluginStub(this, packageName, className, npp);
+                PluginUtil.getPluginStub(this, packageName, className);
 
         if (stub != null) {
-            View pluginView = stub.getFullScreenView(this);
+            View pluginView = stub.getFullScreenView(npp, this);
             if (pluginView != null) {
                 setContentView(pluginView);
             } else {
diff --git a/core/java/android/webkit/PluginStub.java b/core/java/android/webkit/PluginStub.java
index c24da8d..cbb36aa 100644
--- a/core/java/android/webkit/PluginStub.java
+++ b/core/java/android/webkit/PluginStub.java
@@ -19,32 +19,29 @@
 import android.view.View;
 
 /**
- * This abstract class is used to implement plugins in a WebView. A plugin
+ * This interface is used to implement plugins in a WebView. A plugin
  * package may extend this class and implement the abstract functions to create
  * embedded or fullscreeen views displayed in a WebView. The PluginStub
  * implementation will be provided the same NPP instance that is created
  * through the native interface.
  */
-public abstract class PluginStub {
-    /**
-     * Construct a new PluginStub implementation for the given NPP instance.
-     * @param npp The native NPP instance.
-     */
-    public PluginStub(int npp) { }
+public interface PluginStub {
 
     /**
      * Return a custom embedded view to draw the plugin.
+     * @param npp The native NPP instance.
      * @param context The current application's Context.
      * @return A custom View that will be managed by WebView.
      */
-    public abstract View getEmbeddedView(Context context);
+    public abstract View getEmbeddedView(int NPP, Context context);
 
     /**
      * Return a custom full-screen view to be displayed when the user requests
      * a plugin display as full-screen. Note that the application may choose not
      * to display this View as completely full-screen.
+     * @param npp The native NPP instance.
      * @param context The current application's Context.
      * @return A custom View that will be managed by the application.
      */
-    public abstract View getFullScreenView(Context context);
+    public abstract View getFullScreenView(int NPP, Context context);
 }
diff --git a/core/java/android/webkit/PluginUtil.java b/core/java/android/webkit/PluginUtil.java
index c0a7375..8fdbd67 100644
--- a/core/java/android/webkit/PluginUtil.java
+++ b/core/java/android/webkit/PluginUtil.java
@@ -32,19 +32,16 @@
      * @param className the fully qualified name of a subclass of PluginStub
      */
     /* package */
-    static PluginStub getPluginStub(Context context, String packageName,
-            String className, int NPP) {
+    static PluginStub getPluginStub(Context context, String packageName, 
+            String className) {
         try {
             Context pluginContext = context.createPackageContext(packageName,
                     Context.CONTEXT_INCLUDE_CODE |
                     Context.CONTEXT_IGNORE_SECURITY);
             ClassLoader pluginCL = pluginContext.getClassLoader();
 
-            Class<?> stubClass =
-                    pluginCL.loadClass(className);
-            Constructor<?> stubConstructor =
-                    stubClass.getConstructor(int.class);
-            Object stubObject = stubConstructor.newInstance(NPP);
+            Class<?> stubClass = pluginCL.loadClass(className);
+            Object stubObject = stubClass.newInstance();
 
             if (stubObject instanceof PluginStub) {
                 return (PluginStub) stubObject;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2329e21..081f67a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -25,8 +25,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
 import android.graphics.Picture;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -59,7 +57,6 @@
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
 import android.view.animation.AlphaAnimation;
-import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.WebTextView.AutoCompleteAdapter;
 import android.webkit.WebViewCore.EventHub;
@@ -68,9 +65,7 @@
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.ScrollBarDrawable;
 import android.widget.Scroller;
 import android.widget.Toast;
 import android.widget.ZoomButtonsController;
@@ -219,13 +214,13 @@
             inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true);
             mPlusMinusZoomControls = (ZoomControls) findViewById(
                     com.android.internal.R.id.zoomControls);
-            mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify);
+            findViewById(com.android.internal.R.id.zoomMagnify).setVisibility(
+                    View.GONE);
         }
 
         public void show(boolean showZoom, boolean canZoomOut) {
             mPlusMinusZoomControls.setVisibility(
                     showZoom ? View.VISIBLE : View.GONE);
-            mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE);
             fade(View.VISIBLE, 0.0f, 1.0f);
         }
 
@@ -240,12 +235,8 @@
             setVisibility(visibility);
         }
 
-        public void setIsZoomMagnifyEnabled(boolean isEnabled) {
-            mZoomMagnify.setEnabled(isEnabled);
-        }
-
         public boolean hasFocus() {
-            return mPlusMinusZoomControls.hasFocus() || mZoomMagnify.hasFocus();
+            return mPlusMinusZoomControls.hasFocus();
         }
 
         public void setOnZoomInClickListener(OnClickListener listener) {
@@ -256,12 +247,7 @@
             mPlusMinusZoomControls.setOnZoomOutClickListener(listener);
         }
 
-        public void setOnZoomMagnifyClickListener(OnClickListener listener) {
-            mZoomMagnify.setOnClickListener(listener);
-        }
-
         ZoomControls    mPlusMinusZoomControls;
-        ImageView       mZoomMagnify;
     }
 
     /**
@@ -351,9 +337,6 @@
     private float mLastVelX;
     private float mLastVelY;
 
-    // use this flag to control whether enabling the new double tap zoom
-    static final boolean ENABLE_DOUBLETAP_ZOOM = true;
-
     /**
      * Touch mode
      */
@@ -363,17 +346,9 @@
     private static final int TOUCH_DRAG_MODE = 3;
     private static final int TOUCH_SHORTPRESS_START_MODE = 4;
     private static final int TOUCH_SHORTPRESS_MODE = 5;
-    private static final int TOUCH_DOUBLECLICK_MODE = 6;
+    private static final int TOUCH_DOUBLE_TAP_MODE = 6;
     private static final int TOUCH_DONE_MODE = 7;
     private static final int TOUCH_SELECT_MODE = 8;
-    // touch mode values specific to scale+scroll
-    private static final int FIRST_SCROLL_ZOOM = 9;
-    private static final int SCROLL_ZOOM_ANIMATION_IN = 9;
-    private static final int SCROLL_ZOOM_ANIMATION_OUT = 10;
-    private static final int SCROLL_ZOOM_OUT = 11;
-    private static final int LAST_SCROLL_ZOOM = 11;
-    // end of touch mode values specific to scale+scroll
-    private static final int TOUCH_DOUBLE_TAP_MODE = 12;
 
     // Whether to forward the touch events to WebCore
     private boolean mForwardTouchEvents = false;
@@ -1835,23 +1810,50 @@
         return contentToViewDimension(y) + getTitleHeight();
     }
 
+    private Rect contentToViewRect(Rect x) {
+        return new Rect(contentToViewX(x.left), contentToViewY(x.top),
+                        contentToViewX(x.right), contentToViewY(x.bottom));
+    }
+
+    /*  To invalidate a rectangle in content coordinates, we need to transform
+        the rect into view coordinates, so we can then call invalidate(...).
+
+        Normally, we would just call contentToView[XY](...), which eventually
+        calls Math.round(coordinate * mActualScale). However, for invalidates,
+        we need to account for the slop that occurs with antialiasing. To
+        address that, we are a little more liberal in the size of the rect that
+        we invalidate.
+
+        This liberal calculation calls floor() for the top/left, and ceil() for
+        the bottom/right coordinates. This catches the possible extra pixels of
+        antialiasing that we might have missed with just round().
+     */
+
     // Called by JNI to invalidate the View, given rectangle coordinates in
     // content space
     private void viewInvalidate(int l, int t, int r, int b) {
-        invalidate(contentToViewX(l), contentToViewY(t), contentToViewX(r),
-                contentToViewY(b));
+        final float scale = mActualScale;
+        final int dy = getTitleHeight();
+        invalidate((int)Math.floor(l * scale),
+                   (int)Math.floor(t * scale) + dy,
+                   (int)Math.ceil(r * scale),
+                   (int)Math.ceil(b * scale) + dy);
     }
 
     // Called by JNI to invalidate the View after a delay, given rectangle
     // coordinates in content space
     private void viewInvalidateDelayed(long delay, int l, int t, int r, int b) {
-        postInvalidateDelayed(delay, contentToViewX(l), contentToViewY(t),
-                contentToViewX(r), contentToViewY(b));
+        final float scale = mActualScale;
+        final int dy = getTitleHeight();
+        postInvalidateDelayed(delay,
+                              (int)Math.floor(l * scale),
+                              (int)Math.floor(t * scale) + dy,
+                              (int)Math.ceil(r * scale),
+                              (int)Math.ceil(b * scale) + dy);
     }
 
-    private Rect contentToView(Rect x) {
-        return new Rect(contentToViewX(x.left), contentToViewY(x.top)
-                , contentToViewX(x.right), contentToViewY(x.bottom));
+    private void invalidateContentRect(Rect r) {
+        viewInvalidate(r.left, r.top, r.right, r.bottom);
     }
 
     // stop the scroll animation, and don't let a subsequent fling add
@@ -2675,32 +2677,19 @@
         if (mNativeClass == 0) {
             return;
         }
-        if (mWebViewCore.mEndScaleZoom) {
-            mWebViewCore.mEndScaleZoom = false;
-            if (mTouchMode >= FIRST_SCROLL_ZOOM
-                    && mTouchMode <= LAST_SCROLL_ZOOM) {
-                setHorizontalScrollBarEnabled(true);
-                setVerticalScrollBarEnabled(true);
-                mTouchMode = TOUCH_DONE_MODE;
-            }
-        }
         canvas.save();
-        if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
-            scrollZoomDraw(canvas);
-        } else {
-            // Update the buttons in the picture, so when we draw the picture
-            // to the screen, they are in the correct state.
-            // Tell the native side if user is a) touching the screen,
-            // b) pressing the trackball down, or c) pressing the enter key
-            // If the cursor is on a button, we need to draw it in the pressed
-            // state.
-            // If mNativeClass is 0, we should not reach here, so we do not
-            // need to check it again.
-            nativeRecordButtons(hasFocus() && hasWindowFocus(),
-                    mTouchMode == TOUCH_SHORTPRESS_START_MODE
-                    || mTrackballDown || mGotCenterDown, false);
-            drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
-        }
+        // Update the buttons in the picture, so when we draw the picture
+        // to the screen, they are in the correct state.
+        // Tell the native side if user is a) touching the screen,
+        // b) pressing the trackball down, or c) pressing the enter key
+        // If the cursor is on a button, we need to draw it in the pressed
+        // state.
+        // If mNativeClass is 0, we should not reach here, so we do not
+        // need to check it again.
+        nativeRecordButtons(hasFocus() && hasWindowFocus(),
+                mTouchMode == TOUCH_SHORTPRESS_START_MODE
+                || mTrackballDown || mGotCenterDown, false);
+        drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
         canvas.restoreToCount(saveCount);
 
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
@@ -2765,13 +2754,14 @@
                 zoomScale = mZoomScale;
                 // set mZoomScale to be 0 as we have done animation
                 mZoomScale = 0;
+                animateZoom = false;    // inform drawContentPicture we're done
                 if (mNeedToAdjustWebTextView) {
                     mNeedToAdjustWebTextView = false;
                     mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                             contentToViewDimension(
                             nativeFocusCandidateTextSize()));
                     Rect bounds = nativeFocusCandidateNodeBounds();
-                    Rect vBox = contentToView(bounds);
+                    Rect vBox = contentToViewRect(bounds);
                     mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                             vBox.height());
                     // If it is a password field, start drawing the
@@ -2838,371 +2828,6 @@
         }
     }
 
-    private float scrollZoomGridScale(float invScale) {
-        float griddedInvScale = (int) (invScale * SCROLL_ZOOM_GRID)
-            / (float) SCROLL_ZOOM_GRID;
-        return 1.0f / griddedInvScale;
-    }
-
-    private float scrollZoomX(float scale) {
-        int width = getViewWidth();
-        float maxScrollZoomX = mContentWidth * scale - width;
-        int maxX = mContentWidth - width;
-        return -(maxScrollZoomX > 0 ? mZoomScrollX * maxScrollZoomX / maxX
-                : maxScrollZoomX / 2);
-    }
-
-    private float scrollZoomY(float scale) {
-        int height = getViewHeight();
-        float maxScrollZoomY = mContentHeight * scale - height;
-        int maxY = mContentHeight - height;
-        return -(maxScrollZoomY > 0 ? mZoomScrollY * maxScrollZoomY / maxY
-                : maxScrollZoomY / 2);
-    }
-
-    private void drawMagnifyFrame(Canvas canvas, Rect frame, Paint paint) {
-        final float ADORNMENT_LEN = 16.0f;
-        float width = frame.width();
-        float height = frame.height();
-        Path path = new Path();
-        path.moveTo(-ADORNMENT_LEN, -ADORNMENT_LEN);
-        path.lineTo(0, 0);
-        path.lineTo(width, 0);
-        path.lineTo(width + ADORNMENT_LEN, -ADORNMENT_LEN);
-        path.moveTo(-ADORNMENT_LEN, height + ADORNMENT_LEN);
-        path.lineTo(0, height);
-        path.lineTo(width, height);
-        path.lineTo(width + ADORNMENT_LEN, height + ADORNMENT_LEN);
-        path.moveTo(0, 0);
-        path.lineTo(0, height);
-        path.moveTo(width, 0);
-        path.lineTo(width, height);
-        path.offset(frame.left, frame.top);
-        canvas.drawPath(path, paint);
-    }
-
-    // Returns frame surrounding magified portion of screen while
-    // scroll-zoom is enabled. The frame is also used to center the
-    // zoom-in zoom-out points at the start and end of the animation.
-    private Rect scrollZoomFrame(int width, int height, float halfScale) {
-        Rect scrollFrame = new Rect();
-        scrollFrame.set(mZoomScrollX, mZoomScrollY,
-                mZoomScrollX + width, mZoomScrollY + height);
-        if (mContentWidth * mZoomScrollLimit < width) {
-            float scale = zoomFrameScaleX(width, halfScale, 1.0f);
-            float offsetX = (width * scale - width) * 0.5f;
-            scrollFrame.left -= offsetX;
-            scrollFrame.right += offsetX;
-        }
-        if (mContentHeight * mZoomScrollLimit < height) {
-            float scale = zoomFrameScaleY(height, halfScale, 1.0f);
-            float offsetY = (height * scale - height) * 0.5f;
-            scrollFrame.top -= offsetY;
-            scrollFrame.bottom += offsetY;
-        }
-        return scrollFrame;
-    }
-
-    private float zoomFrameScaleX(int width, float halfScale, float noScale) {
-        // mContentWidth > width > mContentWidth * mZoomScrollLimit
-        if (mContentWidth <= width) {
-            return halfScale;
-        }
-        float part = (width - mContentWidth * mZoomScrollLimit)
-                / (width * (1 - mZoomScrollLimit));
-        return halfScale * part + noScale * (1.0f - part);
-    }
-
-    private float zoomFrameScaleY(int height, float halfScale, float noScale) {
-        if (mContentHeight <= height) {
-            return halfScale;
-        }
-        float part = (height - mContentHeight * mZoomScrollLimit)
-                / (height * (1 - mZoomScrollLimit));
-        return halfScale * part + noScale * (1.0f - part);
-    }
-
-    private float scrollZoomMagScale(float invScale) {
-        return (invScale * 2 + mInvActualScale) / 3;
-    }
-
-    private void scrollZoomDraw(Canvas canvas) {
-        float invScale = mZoomScrollInvLimit;
-        int elapsed = 0;
-        if (mTouchMode != SCROLL_ZOOM_OUT) {
-            elapsed = (int) Math.min(System.currentTimeMillis()
-                - mZoomScrollStart, SCROLL_ZOOM_DURATION);
-            float transitionScale = (mZoomScrollInvLimit - mInvActualScale)
-                    * elapsed / SCROLL_ZOOM_DURATION;
-            if (mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
-                invScale = mInvActualScale + transitionScale;
-            } else { /* if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) */
-                invScale = mZoomScrollInvLimit - transitionScale;
-            }
-        }
-        float scale = scrollZoomGridScale(invScale);
-        invScale = 1.0f / scale;
-        int width = getViewWidth();
-        int height = getViewHeight();
-        float halfScale = scrollZoomMagScale(invScale);
-        Rect scrollFrame = scrollZoomFrame(width, height, halfScale);
-        if (elapsed == SCROLL_ZOOM_DURATION) {
-            if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
-                setHorizontalScrollBarEnabled(true);
-                setVerticalScrollBarEnabled(true);
-                rebuildWebTextView();
-                scrollTo((int) (scrollFrame.centerX() * mActualScale)
-                        - (width >> 1), (int) (scrollFrame.centerY()
-                        * mActualScale) - (height >> 1));
-                mTouchMode = TOUCH_DONE_MODE;
-                // Show all the child views once we are done.
-                mViewManager.showAll();
-            } else {
-                mTouchMode = SCROLL_ZOOM_OUT;
-            }
-        }
-        float newX = scrollZoomX(scale);
-        float newY = scrollZoomY(scale);
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "scrollZoomDraw scale=" + scale + " + (" + newX
-                    + ", " + newY + ") mZoomScroll=(" + mZoomScrollX + ", "
-                    + mZoomScrollY + ")" + " invScale=" + invScale + " scale="
-                    + scale);
-        }
-        canvas.translate(newX, newY);
-        canvas.scale(scale, scale);
-        boolean animating = mTouchMode != SCROLL_ZOOM_OUT;
-        if (mDrawHistory) {
-            int sc = canvas.save(Canvas.CLIP_SAVE_FLAG);
-            Rect clip = new Rect(0, 0, mHistoryPicture.getWidth(),
-                    mHistoryPicture.getHeight());
-            canvas.clipRect(clip, Region.Op.DIFFERENCE);
-            canvas.drawColor(mBackgroundColor);
-            canvas.restoreToCount(sc);
-            canvas.drawPicture(mHistoryPicture);
-        } else {
-            mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
-                    animating, true);
-        }
-        if (mTouchMode == TOUCH_DONE_MODE) {
-            return;
-        }
-        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        paint.setStyle(Paint.Style.STROKE);
-        paint.setStrokeWidth(30.0f);
-        paint.setARGB(0x50, 0, 0, 0);
-        int maxX = mContentWidth - width;
-        int maxY = mContentHeight - height;
-        if (true) { // experiment: draw hint to place finger off magnify area
-            drawMagnifyFrame(canvas, scrollFrame, paint);
-        } else {
-            canvas.drawRect(scrollFrame, paint);
-        }
-        int sc = canvas.save();
-        canvas.clipRect(scrollFrame);
-        float halfX = (float) mZoomScrollX / maxX;
-        if (mContentWidth * mZoomScrollLimit < width) {
-            halfX = zoomFrameScaleX(width, 0.5f, halfX);
-        }
-        float halfY = (float) mZoomScrollY / maxY;
-        if (mContentHeight * mZoomScrollLimit < height) {
-            halfY = zoomFrameScaleY(height, 0.5f, halfY);
-        }
-        canvas.scale(halfScale, halfScale, mZoomScrollX + width * halfX
-                , mZoomScrollY + height * halfY);
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "scrollZoomDraw halfScale=" + halfScale + " w/h=("
-                    + width + ", " + height + ") half=(" + halfX + ", "
-                    + halfY + ")");
-        }
-        if (mDrawHistory) {
-            canvas.drawPicture(mHistoryPicture);
-        } else {
-            mWebViewCore.drawContentPicture(canvas, mBackgroundColor,
-                    animating, false);
-        }
-        canvas.restoreToCount(sc);
-        if (mTouchMode != SCROLL_ZOOM_OUT) {
-            invalidate();
-        }
-    }
-
-    private void zoomScrollTap(float x, float y) {
-        float scale = scrollZoomGridScale(mZoomScrollInvLimit);
-        float left = scrollZoomX(scale);
-        float top = scrollZoomY(scale);
-        int width = getViewWidth();
-        int height = getViewHeight();
-        x -= width * scale / 2;
-        y -= height * scale / 2;
-        mZoomScrollX = Math.min(mContentWidth - width
-                , Math.max(0, (int) ((x - left) / scale)));
-        mZoomScrollY = Math.min(mContentHeight - height
-                , Math.max(0, (int) ((y - top) / scale)));
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "zoomScrollTap scale=" + scale + " + (" + left
-                    + ", " + top + ") mZoomScroll=(" + mZoomScrollX + ", "
-                    + mZoomScrollY + ")" + " x=" + x + " y=" + y);
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public boolean canZoomScrollOut() {
-        if (mContentWidth == 0 || mContentHeight == 0) {
-            return false;
-        }
-        int width = getViewWidth();
-        int height = getViewHeight();
-        float x = (float) width / (float) mContentWidth;
-        float y = (float) height / (float) mContentHeight;
-        mZoomScrollLimit = Math.max(DEFAULT_MIN_ZOOM_SCALE, Math.min(x, y));
-        mZoomScrollInvLimit = 1.0f / mZoomScrollLimit;
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "canZoomScrollOut"
-                    + " mInvActualScale=" + mInvActualScale
-                    + " mZoomScrollLimit=" + mZoomScrollLimit
-                    + " mZoomScrollInvLimit=" + mZoomScrollInvLimit
-                    + " mContentWidth=" + mContentWidth
-                    + " mContentHeight=" + mContentHeight
-                    );
-        }
-        // don't zoom out unless magnify area is at least half as wide
-        // or tall as content
-        float limit = mZoomScrollLimit * 2;
-        return mContentWidth >= width * limit
-                || mContentHeight >= height * limit;
-    }
-
-    private void startZoomScrollOut() {
-        setHorizontalScrollBarEnabled(false);
-        setVerticalScrollBarEnabled(false);
-        if (getSettings().getBuiltInZoomControls()) {
-            if (mZoomButtonsController.isVisible()) {
-                mZoomButtonsController.setVisible(false);
-            }
-        } else {
-            if (mZoomControlRunnable != null) {
-                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
-            }
-            if (mZoomControls != null) {
-                mZoomControls.hide();
-            }
-        }
-        int width = getViewWidth();
-        int height = getViewHeight();
-        int halfW = width >> 1;
-        mLastTouchX = halfW;
-        int halfH = height >> 1;
-        mLastTouchY = halfH;
-        abortAnimation();
-        mZoomScrollStart = System.currentTimeMillis();
-        Rect zoomFrame = scrollZoomFrame(width, height
-                , scrollZoomMagScale(mZoomScrollInvLimit));
-        mZoomScrollX = Math.max(0, (int) ((mScrollX + halfW) * mInvActualScale)
-                - (zoomFrame.width() >> 1));
-        mZoomScrollY = Math.max(0, (int) ((mScrollY + halfH) * mInvActualScale)
-                - (zoomFrame.height() >> 1));
-        scrollTo(0, 0); // triggers inval, starts animation
-        clearTextEntry();
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "startZoomScrollOut mZoomScroll=("
-                    + mZoomScrollX + ", " + mZoomScrollY +")");
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void zoomScrollOut() {
-        if (canZoomScrollOut() == false) {
-            mTouchMode = TOUCH_DONE_MODE;
-            return;
-        }
-        // Hide the child views while in this mode.
-        mViewManager.hideAll();
-        startZoomScrollOut();
-        mTouchMode = SCROLL_ZOOM_ANIMATION_OUT;
-        invalidate();
-    }
-
-    private void moveZoomScrollWindow(float x, float y) {
-        if (Math.abs(x - mLastZoomScrollRawX) < 1.5f
-                && Math.abs(y - mLastZoomScrollRawY) < 1.5f) {
-            return;
-        }
-        mLastZoomScrollRawX = x;
-        mLastZoomScrollRawY = y;
-        int oldX = mZoomScrollX;
-        int oldY = mZoomScrollY;
-        int width = getViewWidth();
-        int height = getViewHeight();
-        int maxZoomX = mContentWidth - width;
-        if (maxZoomX > 0) {
-            int maxScreenX = width - (int) Math.ceil(width
-                    * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "moveZoomScrollWindow-X"
-                        + " maxScreenX=" + maxScreenX + " width=" + width
-                        + " mZoomScrollLimit=" + mZoomScrollLimit + " x=" + x);
-            }
-            x += maxScreenX * mLastScrollX / maxZoomX - mLastTouchX;
-            x *= Math.max(maxZoomX / maxScreenX, mZoomScrollInvLimit);
-            mZoomScrollX = Math.max(0, Math.min(maxZoomX, (int) x));
-        }
-        int maxZoomY = mContentHeight - height;
-        if (maxZoomY > 0) {
-            int maxScreenY = height - (int) Math.ceil(height
-                    * mZoomScrollLimit) - SCROLL_ZOOM_FINGER_BUFFER;
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "moveZoomScrollWindow-Y"
-                        + " maxScreenY=" + maxScreenY + " height=" + height
-                        + " mZoomScrollLimit=" + mZoomScrollLimit + " y=" + y);
-            }
-            y += maxScreenY * mLastScrollY / maxZoomY - mLastTouchY;
-            y *= Math.max(maxZoomY / maxScreenY, mZoomScrollInvLimit);
-            mZoomScrollY = Math.max(0, Math.min(maxZoomY, (int) y));
-        }
-        if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
-            invalidate();
-        }
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "moveZoomScrollWindow"
-                    + " scrollTo=(" + mZoomScrollX + ", " + mZoomScrollY + ")"
-                    + " mLastTouch=(" + mLastTouchX + ", " + mLastTouchY + ")"
-                    + " maxZoom=(" + maxZoomX + ", " + maxZoomY + ")"
-                    + " last=("+mLastScrollX+", "+mLastScrollY+")"
-                    + " x=" + x + " y=" + y);
-        }
-    }
-
-    private void setZoomScrollIn() {
-        mZoomScrollStart = System.currentTimeMillis();
-    }
-
-    private float mZoomScrollLimit;
-    private float mZoomScrollInvLimit;
-    private int mLastScrollX;
-    private int mLastScrollY;
-    private long mZoomScrollStart;
-    private int mZoomScrollX;
-    private int mZoomScrollY;
-    private float mLastZoomScrollRawX = -1000.0f;
-    private float mLastZoomScrollRawY = -1000.0f;
-    // The zoomed scale varies from 1.0 to DEFAULT_MIN_ZOOM_SCALE == 0.25.
-    // The zoom animation duration SCROLL_ZOOM_DURATION == 0.5.
-    // Two pressures compete for gridding; a high frame rate (e.g. 20 fps)
-    // and minimizing font cache allocations (fewer frames is better).
-    // A SCROLL_ZOOM_GRID of 6 permits about 20 zoom levels over 0.5 seconds:
-    // the inverse of: 1.0, 1.16, 1.33, 1.5, 1.67, 1.84, 2.0, etc. to 4.0
-    private static final int SCROLL_ZOOM_GRID = 6;
-    private static final int SCROLL_ZOOM_DURATION = 500;
-    // Make it easier to get to the bottom of a document by reserving a 32
-    // pixel buffer, for when the starting drag is a bit below the bottom of
-    // the magnify frame.
-    private static final int SCROLL_ZOOM_FINGER_BUFFER = 32;
-
     // draw history
     private boolean mDrawHistory = false;
     private Picture mHistoryPicture = null;
@@ -3312,9 +2937,7 @@
      */
     /* package */ void rebuildWebTextView() {
         // If the WebView does not have focus, do nothing until it gains focus.
-        if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())
-                || (mTouchMode >= FIRST_SCROLL_ZOOM
-                && mTouchMode <= LAST_SCROLL_ZOOM)) {
+        if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())) {
             return;
         }
         boolean alreadyThere = inEditingMode();
@@ -3365,7 +2988,7 @@
                 Selection.setSelection(spannable, start, end);
             }
         } else {
-            Rect vBox = contentToView(bounds);
+            Rect vBox = contentToViewRect(bounds);
             mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                     vBox.height());
             mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
@@ -3479,11 +3102,9 @@
 
         // Bubble up the key event if
         // 1. it is a system key; or
-        // 2. the host application wants to handle it; or
-        // 3. webview is in scroll-zoom state;
+        // 2. the host application wants to handle it;
         if (event.isSystem()
-                || mCallbackProxy.uiOverrideKeyEvent(event)
-                || (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM)) {
+                || mCallbackProxy.uiOverrideKeyEvent(event)) {
             return false;
         }
 
@@ -3630,18 +3251,6 @@
             return false;
         }
 
-        // special handling in scroll_zoom state
-        if (mTouchMode >= FIRST_SCROLL_ZOOM && mTouchMode <= LAST_SCROLL_ZOOM) {
-            if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode
-                    && mTouchMode != SCROLL_ZOOM_ANIMATION_IN) {
-                setZoomScrollIn();
-                mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
-                invalidate();
-                return true;
-            }
-            return false;
-        }
-
         if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
                 || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
             if (commitCopy()) {
@@ -3962,11 +3571,8 @@
         }
 
         // pass the touch events from UI thread to WebCore thread
-        if (mForwardTouchEvents && mTouchMode != SCROLL_ZOOM_OUT
-                && mTouchMode != SCROLL_ZOOM_ANIMATION_IN
-                && mTouchMode != SCROLL_ZOOM_ANIMATION_OUT
-                && (action != MotionEvent.ACTION_MOVE ||
-                        eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
+        if (mForwardTouchEvents && (action != MotionEvent.ACTION_MOVE
+                || eventTime - mLastSentTouchTime > TOUCH_SENT_INTERVAL)) {
             WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData();
             ted.mAction = action;
             ted.mX = viewToContentX((int) x + mScrollX);
@@ -3980,15 +3586,7 @@
 
         switch (action) {
             case MotionEvent.ACTION_DOWN: {
-                if (mTouchMode == SCROLL_ZOOM_ANIMATION_IN
-                        || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
-                    // no interaction while animation is in progress
-                    break;
-                } else if (mTouchMode == SCROLL_ZOOM_OUT) {
-                    mLastScrollX = mZoomScrollX;
-                    mLastScrollY = mZoomScrollY;
-                    // If two taps are close, ignore the first tap
-                } else if (!mScroller.isFinished()) {
+                if (!mScroller.isFinished()) {
                     // stop the current scroll animation, but if this is
                     // the start of a fling, allow it to add to the current
                     // fling's velocity
@@ -4039,17 +3637,10 @@
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
-                if (mTouchMode == TOUCH_DONE_MODE
-                        || mTouchMode == SCROLL_ZOOM_ANIMATION_IN
-                        || mTouchMode == SCROLL_ZOOM_ANIMATION_OUT) {
+                if (mTouchMode == TOUCH_DONE_MODE) {
                     // no dragging during scroll zoom animation
                     break;
                 }
-                if (mTouchMode == SCROLL_ZOOM_OUT) {
-                    // while fully zoomed out, move the virtual window
-                    moveZoomScrollWindow(x, y);
-                    break;
-                }
                 mVelocityTracker.addMovement(ev);
 
                 if (mTouchMode != TOUCH_DRAG_MODE) {
@@ -4097,8 +3688,7 @@
                     if (settings.supportZoom()
                             && settings.getBuiltInZoomControls()
                             && !mZoomButtonsController.isVisible()
-                            && (canZoomScrollOut() ||
-                                    mMinZoomScale < mMaxZoomScale)) {
+                            && mMinZoomScale < mMaxZoomScale) {
                         mZoomButtonsController.setVisible(true);
                     }
                 }
@@ -4165,12 +3755,11 @@
 
                 if (!getSettings().getBuiltInZoomControls()) {
                     boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
-                    boolean showMagnify = canZoomScrollOut();
-                    if (mZoomControls != null && (showPlusMinus || showMagnify)) {
+                    if (mZoomControls != null && showPlusMinus) {
                         if (mZoomControls.getVisibility() == View.VISIBLE) {
                             mPrivateHandler.removeCallbacks(mZoomControlRunnable);
                         } else {
-                            mZoomControls.show(showPlusMinus, showMagnify);
+                            mZoomControls.show(showPlusMinus, false);
                         }
                         mPrivateHandler.postDelayed(mZoomControlRunnable,
                                 ZOOM_CONTROLS_TIMEOUT);
@@ -4193,17 +3782,14 @@
                         doDoubleTap();
                         break;
                     case TOUCH_INIT_MODE: // tap
-                        if (ENABLE_DOUBLETAP_ZOOM) {
-                            mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                            if (!mPreventDrag) {
-                                mPrivateHandler.sendMessageDelayed(
-                                        mPrivateHandler.obtainMessage(
-                                        RELEASE_SINGLE_TAP),
-                                        ViewConfiguration.getDoubleTapTimeout());
-                            }
-                            break;
+                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                        if (!mPreventDrag) {
+                            mPrivateHandler.sendMessageDelayed(
+                                    mPrivateHandler.obtainMessage(
+                                    RELEASE_SINGLE_TAP),
+                                    ViewConfiguration.getDoubleTapTimeout());
                         }
-                        // fall through
+                        break;
                     case TOUCH_SHORTPRESS_START_MODE:
                     case TOUCH_SHORTPRESS_MODE:
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4215,29 +3801,9 @@
                         commitCopy();
                         mTouchSelection = false;
                         break;
-                    case SCROLL_ZOOM_ANIMATION_IN:
-                    case SCROLL_ZOOM_ANIMATION_OUT:
-                        // no action during scroll animation
-                        break;
-                    case SCROLL_ZOOM_OUT:
-                        if (DebugFlags.WEB_VIEW) {
-                            Log.v(LOGTAG, "ACTION_UP SCROLL_ZOOM_OUT"
-                                    + " eventTime - mLastTouchTime="
-                                    + (eventTime - mLastTouchTime));
-                        }
-                        // for now, always zoom back when the drag completes
-                        if (true || eventTime - mLastTouchTime < TAP_TIMEOUT) {
-                            // but if we tap, zoom in where we tap
-                            if (eventTime - mLastTouchTime < TAP_TIMEOUT) {
-                                zoomScrollTap(x, y);
-                            }
-                            // start zooming in back to the original view
-                            setZoomScrollIn();
-                            mTouchMode = SCROLL_ZOOM_ANIMATION_IN;
-                            invalidate();
-                        }
-                        break;
                     case TOUCH_DRAG_MODE:
+                        // redraw in high-quality, as we're done dragging
+                        invalidate();
                         // if the user waits a while w/o moving before the
                         // up, we don't want to do a fling
                         if (eventTime - mLastTouchTime <= MIN_FLING_TIME) {
@@ -4270,10 +3836,7 @@
                     mVelocityTracker.recycle();
                     mVelocityTracker = null;
                 }
-                if (mTouchMode == SCROLL_ZOOM_OUT ||
-                        mTouchMode == SCROLL_ZOOM_ANIMATION_IN) {
-                    scrollTo(mZoomScrollX, mZoomScrollY);
-                } else if (mTouchMode == TOUCH_DRAG_MODE) {
+                if (mTouchMode == TOUCH_DRAG_MODE) {
                     WebViewCore.resumeUpdate(mWebViewCore);
                 }
                 mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4372,11 +3935,6 @@
             if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
             return false;
         }
-        // no move if we're still waiting on SWITCH_TO_CLICK timeout
-        if (mTouchMode == TOUCH_DOUBLECLICK_MODE) {
-            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent 2 click quit");
-            return true;
-        }
         if (mTrackballDown) {
             if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent down quit");
             return true; // discard move if trackball is down
@@ -4512,25 +4070,6 @@
         int height = mContentHeight - getViewHeight();
         if (width < 0) width = 0;
         if (height < 0) height = 0;
-        if (mTouchMode == SCROLL_ZOOM_OUT) {
-            int oldX = mZoomScrollX;
-            int oldY = mZoomScrollY;
-            int maxWH = Math.max(width, height);
-            mZoomScrollX += scaleTrackballX(xRate, maxWH);
-            mZoomScrollY += scaleTrackballY(yRate, maxWH);
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "doTrackball SCROLL_ZOOM_OUT"
-                        + " mZoomScrollX=" + mZoomScrollX
-                        + " mZoomScrollY=" + mZoomScrollY);
-            }
-            mZoomScrollX = Math.min(width, Math.max(0, mZoomScrollX));
-            mZoomScrollY = Math.min(height, Math.max(0, mZoomScrollY));
-            if (oldX != mZoomScrollX || oldY != mZoomScrollY) {
-                invalidate();
-            }
-            mTrackballRemainsX = mTrackballRemainsY = 0;
-            return;
-        }
         ax = Math.abs(mTrackballRemainsX * TRACKBALL_MULTIPLIER);
         ay = Math.abs(mTrackballRemainsY * TRACKBALL_MULTIPLIER);
         maxA = Math.max(ax, ay);
@@ -4750,14 +4289,6 @@
                 zoomOut();
             }
         });
-        zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() {
-            public void onClick(View v) {
-                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
-                mPrivateHandler.postDelayed(mZoomControlRunnable,
-                        ZOOM_CONTROLS_TIMEOUT);
-                zoomScrollOut();
-            }
-        });
         return zoomControls;
     }
 
@@ -4802,7 +4333,7 @@
         // TODO: alternatively we can disallow this during draw history mode
         switchOutDrawHistory();
         float scale = mActualScale * 0.8f;
-        if (scale < (mMinZoomScale + 0.1f) && WebView.ENABLE_DOUBLETAP_ZOOM
+        if (scale < (mMinZoomScale + 0.1f)
                 && mWebViewCore.getSettings().getUseWideViewPort()) {
             // when zoom out to min scale, switch to overview mode
             doDoubleTap();
@@ -4889,6 +4420,9 @@
         // In case the soft keyboard has been dismissed, bring it back up.
         InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
                 0);
+        if (nativeFocusNodePointer() != nativeCursorNodePointer()) {
+            nativeMotionUp(x, y, mNavSlop);
+        }
         nativeTextInputMotionUp(x, y);
     }
 
@@ -5259,7 +4793,7 @@
                         setNewZoomScale(mLastScale, false);
                         setContentScrollTo(restoreState.mScrollX,
                                 restoreState.mScrollY);
-                        if (ENABLE_DOUBLETAP_ZOOM && useWideViewport
+                        if (useWideViewport
                                 && settings.getLoadWithOverviewMode()) {
                             if (restoreState.mViewScale == 0
                                     || (restoreState.mMobileSite
@@ -5286,7 +4820,7 @@
                         Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
                                 b.left+","+b.top+","+b.right+","+b.bottom+"}");
                     }
-                    invalidate(contentToView(draw.mInvalRegion.getBounds()));
+                    invalidateContentRect(draw.mInvalRegion.getBounds());
                     if (mPictureListener != null) {
                         mPictureListener.onNewPicture(WebView.this, capturePicture());
                     }
@@ -5745,7 +5279,7 @@
         // FIXME the divisor should be retrieved from somewhere
         // the closest thing today is hard-coded into ScrollView.java
         // (from ScrollView.java, line 363)   int maxJump = height/2;
-        return viewToContentY(height);
+        return Math.round(height * mInvActualScale);
     }
 
     /**
@@ -5785,7 +5319,7 @@
         }
         Rect contentCursorRingBounds = nativeGetCursorRingBounds();
         if (contentCursorRingBounds.isEmpty()) return keyHandled;
-        Rect viewCursorRingBounds = contentToView(contentCursorRingBounds);
+        Rect viewCursorRingBounds = contentToViewRect(contentCursorRingBounds);
         Rect visRect = new Rect();
         calcOurVisibleRect(visRect);
         Rect outset = new Rect(visRect);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 26d9343..ac3334c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -34,10 +34,10 @@
 import android.view.KeyEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
+import android.view.View;
 
 import java.util.ArrayList;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 
 import junit.framework.Assert;
@@ -838,9 +838,11 @@
                         case DESTROY:
                             // Time to take down the world. Cancel all pending
                             // loads and destroy the native view and frame.
-                            mBrowserFrame.destroy();
-                            mBrowserFrame = null;
-                            mNativeClass = 0;
+                            synchronized (WebViewCore.this) {
+                                mBrowserFrame.destroy();
+                                mBrowserFrame = null;
+                                mNativeClass = 0;
+                            }
                             break;
 
                         case UPDATE_FRAME_CACHE_IF_LOADING:
@@ -1528,9 +1530,6 @@
     // Used to suspend drawing.
     private boolean mDrawIsPaused;
 
-    // Used to end scale+scroll mode, accessed by both threads
-    boolean mEndScaleZoom = false;
-
     // mRestoreState is set in didFirstLayout(), and reset in the next
     // webkitDraw after passing it to the UI thread.
     private RestoreState mRestoreState = null;
@@ -1571,7 +1570,7 @@
             // Send the native view size that was used during the most recent
             // layout.
             draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
-            if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) {
+            if (mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = Math.max(
                         mViewportWidth == -1 ? DEFAULT_VIEWPORT_WIDTH
                                 : (mViewportWidth == 0 ? mCurrentViewWidth
@@ -1627,11 +1626,11 @@
         }
     }
 
-    /* package */ boolean pictureReady() {
+    /* package */ synchronized boolean pictureReady() {
         return nativePictureReady();
     }
 
-    /*package*/ Picture copyContentPicture() {
+    /*package*/ synchronized Picture copyContentPicture() {
         Picture result = new Picture();
         nativeCopyContentToPicture(result);
         return result;
@@ -1977,7 +1976,7 @@
 
     // called by JNI
     private void restoreScreenWidthScale(int scale) {
-        if (!WebView.ENABLE_DOUBLETAP_ZOOM || !mSettings.getUseWideViewPort()) {
+        if (!mSettings.getUseWideViewPort()) {
             return;
         }
 
@@ -2062,84 +2061,32 @@
         }
     }
 
-    // This class looks like a SurfaceView to native code. In java, we can
-    // assume the passed in SurfaceView is this class so we can talk to the
-    // ViewManager through the ChildView.
-    private class SurfaceViewProxy extends SurfaceView
-            implements SurfaceHolder.Callback {
-        private final ViewManager.ChildView mChildView;
-        private int mPointer;
-        private final boolean mIsFixedSize;
-        SurfaceViewProxy(Context context, ViewManager.ChildView childView,
-                int pointer, int pixelFormat, boolean isFixedSize) {
-            super(context);
-            setWillNotDraw(false); // this prevents the black box artifact
-            getHolder().addCallback(this);
-            getHolder().setFormat(pixelFormat);
-            mChildView = childView;
-            mChildView.mView = this;
-            mPointer = pointer;
-            mIsFixedSize = isFixedSize;
-        }
-        void destroy() {
-            mPointer = 0;
-            mChildView.removeView();
-        }
-        void attach(int x, int y, int width, int height) {
-            mChildView.attachView(x, y, width, height);
-
-            if (mIsFixedSize) {
-                getHolder().setFixedSize(width, height);
-            }
-        }
-
-        // SurfaceHolder.Callback methods
-        public void surfaceCreated(SurfaceHolder holder) {
-            if (mPointer != 0) {
-                nativeSurfaceChanged(mPointer, 0, 0, 0, 0);
-            }
-        }
-        public void surfaceChanged(SurfaceHolder holder, int format, int width,
-                int height) {
-            if (mPointer != 0) {
-                nativeSurfaceChanged(mPointer, 1, format, width, height);
-            }
-        }
-        public void surfaceDestroyed(SurfaceHolder holder) {
-            if (mPointer != 0) {
-                nativeSurfaceChanged(mPointer, 2, 0, 0, 0);
-            }
-        }
-    }
-
-    // PluginWidget functions for mainting SurfaceViews for the Surface drawing
+    // PluginWidget functions for creating SurfaceViews for the Surface drawing
     // model.
-    private SurfaceView createSurface(int nativePointer, int pixelFormat,
-                                      boolean isFixedSize) {
+    private ViewManager.ChildView createSurface(String packageName, String className,
+            int npp, int x, int y, int width, int height) {
         if (mWebView == null) {
             return null;
         }
-        return new SurfaceViewProxy(mContext, mWebView.mViewManager.createView(),
-                                    nativePointer, pixelFormat, isFixedSize);
+        PluginStub stub = PluginUtil.getPluginStub(mWebView.getContext(), packageName, className);
+        if (stub == null) {
+            Log.e(LOGTAG, "Unable to find plugin class (" + className + 
+                    ") in the apk (" + packageName + ")");
+            return null;
+        }
+        
+        View pluginView = stub.getEmbeddedView(npp, mWebView.getContext());
+        
+        ViewManager.ChildView view = mWebView.mViewManager.createView();
+        view.mView = pluginView;
+        view.attachView(x, y, width, height);
+        return view;
     }
-
-    private void destroySurface(SurfaceView surface) {
-        SurfaceViewProxy proxy = (SurfaceViewProxy) surface;
-        proxy.destroy();
+    
+    private void destroySurface(ViewManager.ChildView childView) {
+        childView.removeView();
     }
 
-    private void attachSurface(SurfaceView surface, int x, int y,
-            int width, int height) {
-        SurfaceViewProxy proxy = (SurfaceViewProxy) surface;
-        proxy.attach(x, y, width, height);
-    }
-
-    // Callback for the SurfaceHolder.Callback. Called for all the surface
-    // callbacks. The state parameter is one of Created(0), Changed(1),
-    // Destroyed(2).
-    private native void nativeSurfaceChanged(int pointer, int state, int format,
-            int width, int height);
-
     private native void nativePause();
     private native void nativeResume();
     private native void nativeFreeMemory();
diff --git a/core/java/android/widget/FasttrackBadgeWidget.java b/core/java/android/widget/FasttrackBadgeWidget.java
new file mode 100644
index 0000000..22ca5fd
--- /dev/null
+++ b/core/java/android/widget/FasttrackBadgeWidget.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+
+/**
+ * Widget used to show an image with the standard fasttrack badge
+ * and on-click behavior.
+ *
+ * @hide
+ */
+public class FasttrackBadgeWidget extends ImageView implements OnClickListener {
+
+    private Uri mContactUri;
+    private String mContactEmail;
+    private String mContactPhone;
+    private int mMode;
+    private QueryHandler mQueryHandler;
+
+    protected String[] mExcludeMimes = null;
+
+    static final private int TOKEN_EMAIL_LOOKUP = 0;
+    static final private int TOKEN_PHONE_LOOKUP = 1;
+    static final private int TOKEN_EMAIL_LOOKUP_AND_TRIGGER = 2;
+    static final private int TOKEN_PHONE_LOOKUP_AND_TRIGGER = 3;
+
+    static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
+        RawContacts.CONTACT_ID,
+        Contacts.LOOKUP_KEY,
+    };
+    static int EMAIL_ID_COLUMN_INDEX = 0;
+    static int EMAIL_LOOKUP_STRING_COLUMN_INDEX = 1;
+
+    static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
+        PhoneLookup._ID,
+        PhoneLookup.LOOKUP_KEY,
+    };
+    static int PHONE_ID_COLUMN_INDEX = 0;
+    static int PHONE_LOOKUP_STRING_COLUMN_INDEX = 1;
+
+
+
+    public FasttrackBadgeWidget(Context context) {
+        this(context, null);
+    }
+
+    public FasttrackBadgeWidget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public FasttrackBadgeWidget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a =
+            context.obtainStyledAttributes(attrs,
+                    com.android.internal.R.styleable.FasttrackBadgeWidget, defStyle, 0);
+
+        mMode = a.getInt(com.android.internal.R.styleable.FasttrackBadgeWidget_fasttrackWindowSize,
+                Intents.MODE_MEDIUM);
+
+        a.recycle();
+
+        init();
+    }
+
+    private void init() {
+        mQueryHandler = new QueryHandler(mContext.getContentResolver());
+        setOnClickListener(this);
+    }
+
+    /**
+     * Assign the contact uri that this fasttrack badge should be associated with.
+     * Note that this is only used for displaying the fasttrack window and won't
+     * bind the contact's photo for you.
+     *
+     * @param conatctUri Either a {Contacts.CONTENT_URI} or {Contacts.CONTENT_LOOKUP_URI}
+     * style URI.
+     */
+    public void assignContactUri(Uri contactUri) {
+        mContactUri = contactUri;
+    }
+
+    /**
+     * Assign a contact based on an email address. This should only be used when
+     * the contact's URI is not available, as an extra query will have to be
+     * performed to lookup the URI based on the email.
+     *
+     * @param emailAddress The email address of the contact.
+     * @param lazyLookup If this is true, the lookup query will not be performed
+     * until this view is clicked.
+     */
+    public void assignContactFromEmail(String emailAddress, boolean lazyLookup) {
+        mContactEmail = emailAddress;
+        if (!lazyLookup) {
+            mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
+                    Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
+                    EMAIL_LOOKUP_PROJECTION, null, null, null);
+        }
+    }
+
+    /**
+     * Assign a contact based on a phone number. This should only be used when
+     * the contact's URI is not available, as an extra query will have to be
+     * performed to lookup the URI based on the phone number.
+     *
+     * @param phoneNumber The phone number of the contact.
+     * @param lazyLookup If this is true, the lookup query will not be performed
+     * until this view is clicked.
+     */
+    public void assignContactFromPhone(String phoneNumber, boolean lazyLookup) {
+        mContactPhone = phoneNumber;
+        if (!lazyLookup) {
+            mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
+                    Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
+                    PHONE_LOOKUP_PROJECTION, null, null, null);
+        }
+    }
+
+    /**
+     * Set the fasttrack window mode. Options are {@link Intents.MODE_SMALL},
+     * {@link Intents.MODE_MEDIUM}, {@link Intents.MODE_LARGE}.
+     * @param size
+     */
+    public void setMode(int size) {
+        mMode = size;
+    }
+
+    public void onClick(View v) {
+        final Rect target = getTargetRect(v);
+
+        if (mContactUri != null) {
+            trigger(mContactUri, target);
+        } else if (mContactEmail != null) {
+            mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, target,
+                    Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
+                    EMAIL_LOOKUP_PROJECTION, null, null, null);
+        } else if (mContactPhone != null) {
+            mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, target,
+                    Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
+                    PHONE_LOOKUP_PROJECTION, null, null, null);
+        } else {
+            // If a contact hasn't been assigned, don't react to click.
+            return;
+        }
+    }
+
+    /**
+     * Set a list of specific MIME-types to exclude and not display. For
+     * example, this can be used to hide the {@link Contacts#CONTENT_ITEM_TYPE}
+     * profile icon.
+     */
+    public void setExcludeMimes(String[] excludeMimes) {
+        mExcludeMimes = excludeMimes;
+    }
+
+    private void trigger(Uri contactUri, Rect target) {
+        Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, contactUri);
+        intent.putExtra(Intents.EXTRA_TARGET_RECT, target);
+        intent.putExtra(Intents.EXTRA_MODE, mMode);
+        mContext.startActivity(intent);
+    }
+
+    private Rect getTargetRect(View anchor) {
+        final int[] location = new int[2];
+        anchor.getLocationOnScreen(location);
+
+        final Rect rect = new Rect();
+        rect.left = location[0];
+        rect.top = location[1];
+        rect.right = rect.left + anchor.getWidth();
+        rect.bottom = rect.top + anchor.getHeight();
+        return rect;
+    }
+
+    private class QueryHandler extends AsyncQueryHandler {
+
+        public QueryHandler(ContentResolver cr) {
+            super(cr);
+        }
+
+        @Override
+        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+            Uri contactUri = null;
+            boolean trigger = false;
+
+            try{
+                switch(token) {
+                    case TOKEN_PHONE_LOOKUP_AND_TRIGGER:
+                        trigger = true;
+                    case TOKEN_PHONE_LOOKUP: {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
+                            String lookupKey = cursor.getString(PHONE_LOOKUP_STRING_COLUMN_INDEX);
+                            contactUri = Contacts.getLookupUri(contactId, lookupKey);
+                        }
+                        break;
+                    }
+                    case TOKEN_EMAIL_LOOKUP_AND_TRIGGER:
+                        trigger = true;
+                    case TOKEN_EMAIL_LOOKUP: {
+                        if (cursor != null && cursor.moveToFirst()) {
+                            long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
+                            String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
+                            contactUri = Contacts.getLookupUri(contactId, lookupKey);
+                        }
+                    }
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+
+            if (contactUri != null) {
+                mContactUri = contactUri;
+                if (trigger && cookie != null) {
+                    trigger(contactUri, (Rect) cookie);
+                }
+            }
+        }
+    }
+}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 9ec8347..33e83c3 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1148,9 +1148,12 @@
             if (sel != null) {
                positionSelector(sel);
                mSelectedTop = sel.getTop();
+            } else if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
+                View child = getChildAt(mMotionPosition - mFirstPosition);
+                positionSelector(child);
             } else {
-               mSelectedTop = 0;
-               mSelectorRect.setEmpty();
+                mSelectedTop = 0;
+                mSelectorRect.setEmpty();
             }
 
             mLayoutMode = LAYOUT_NORMAL;
@@ -1231,8 +1234,12 @@
     private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
             boolean selected, boolean recycled, int where) {
         boolean isSelected = selected && shouldShowSelector();
-
         final boolean updateChildSelected = isSelected != child.isSelected();
+        final int mode = mTouchMode;
+        final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
+                mMotionPosition == position;
+        final boolean updateChildPressed = isPressed != child.isPressed();
+        
         boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
 
         // Respect layout params that are already in the view. Otherwise make
@@ -1257,6 +1264,10 @@
             }
         }
 
+        if (updateChildPressed) {
+            child.setPressed(isPressed);
+        }
+
         if (needToMeasure) {
             int childHeightSpec = ViewGroup.getChildMeasureSpec(
                     MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 6316864..41c9267 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1542,37 +1542,42 @@
             recycleBin.scrapActiveViews();
 
             if (sel != null) {
-               // the current selected item should get focus if items
-               // are focusable
-               if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
-                   final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
-                           focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
-                   if (!focusWasTaken) {
-                       // selected item didn't take focus, fine, but still want
-                       // to make sure something else outside of the selected view
-                       // has focus
-                       final View focused = getFocusedChild();
-                       if (focused != null) {
-                           focused.clearFocus();
-                       }
-                       positionSelector(sel);
-                   } else {
-                       sel.setSelected(false);
-                       mSelectorRect.setEmpty();
-                   }
-               } else {
-                   positionSelector(sel);
-               }
-               mSelectedTop = sel.getTop();
+                // the current selected item should get focus if items
+                // are focusable
+                if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
+                    final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
+                            focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
+                    if (!focusWasTaken) {
+                        // selected item didn't take focus, fine, but still want
+                        // to make sure something else outside of the selected view
+                        // has focus
+                        final View focused = getFocusedChild();
+                        if (focused != null) {
+                            focused.clearFocus();
+                        }
+                        positionSelector(sel);
+                    } else {
+                        sel.setSelected(false);
+                        mSelectorRect.setEmpty();
+                    }
+                } else {
+                    positionSelector(sel);
+                }
+                mSelectedTop = sel.getTop();
             } else {
-               mSelectedTop = 0;
-               mSelectorRect.setEmpty();
+                if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
+                    View child = getChildAt(mMotionPosition - mFirstPosition);
+                    positionSelector(child);
+                } else {
+                    mSelectedTop = 0;
+                    mSelectorRect.setEmpty();
+                }
 
-               // even if there is not selected position, we may need to restore
-               // focus (i.e. something focusable in touch mode)
-               if (hasFocus() && focusLayoutRestoreView != null) {
-                   focusLayoutRestoreView.requestFocus();
-               }
+                // even if there is not selected position, we may need to restore
+                // focus (i.e. something focusable in touch mode)
+                if (hasFocus() && focusLayoutRestoreView != null) {
+                    focusLayoutRestoreView.requestFocus();
+                }
             }
 
             // tell focus view we are done mucking with it, if it is still in
@@ -1686,6 +1691,10 @@
             boolean selected, boolean recycled) {
         final boolean isSelected = selected && shouldShowSelector();
         final boolean updateChildSelected = isSelected != child.isSelected();
+        final int mode = mTouchMode;
+        final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
+                mMotionPosition == position;
+        final boolean updateChildPressed = isPressed != child.isPressed();
         final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
 
         // Respect layout params that are already in the view. Otherwise make some up...
@@ -1711,6 +1720,10 @@
             child.setSelected(isSelected);
         }
 
+        if (updateChildPressed) {
+            child.setPressed(isPressed);
+        }
+
         if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
             if (child instanceof Checkable) {
                 ((Checkable) child).setChecked(mCheckStates.get(position));
diff --git a/core/res/res/drawable/fasttrack_badge_middle.xml b/core/res/res/drawable/fasttrack_badge_middle_large.xml
similarity index 85%
rename from core/res/res/drawable/fasttrack_badge_middle.xml
rename to core/res/res/drawable/fasttrack_badge_middle_large.xml
index 6df230a..dd591bd 100644
--- a/core/res/res/drawable/fasttrack_badge_middle.xml
+++ b/core/res/res/drawable/fasttrack_badge_middle_large.xml
@@ -19,10 +19,10 @@
         android:state_focused="false"
         android:state_selected="false"
         android:state_pressed="false"
-        android:drawable="@drawable/fasttrack_badge_middle_normal" />
+        android:drawable="@drawable/fasttrack_badge_middle_large_normal" />
 
     <item
         android:state_pressed="true"
-        android:drawable="@drawable/fasttrack_badge_middle_pressed" />
+        android:drawable="@drawable/fasttrack_badge_middle_large_pressed" />
 
 </selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png b/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png
new file mode 100644
index 0000000..ca275cd
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_badge_middle_large_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png b/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png
new file mode 100644
index 0000000..b69ccbd
--- /dev/null
+++ b/core/res/res/drawable/fasttrack_badge_middle_large_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_normal.9.png b/core/res/res/drawable/fasttrack_badge_middle_normal.9.png
deleted file mode 100644
index 07df063..0000000
--- a/core/res/res/drawable/fasttrack_badge_middle_normal.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png b/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png
deleted file mode 100644
index ded95f6..0000000
--- a/core/res/res/drawable/fasttrack_badge_middle_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index ba91e00..8d7e470 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -24,12 +24,12 @@
     android:gravity="center_vertical">
     
     <ImageView android:id="@+id/photo"
-        android:layout_width="48dip"
-        android:layout_height="52dip"
+        android:layout_width="56dip"
+        android:layout_height="62dip"
         android:layout_marginRight="10dip"
         android:layout_marginLeft="10dip"
         android:scaleType="fitCenter"
-        android:background="@drawable/fasttrack_badge_middle"/>
+        android:background="@drawable/fasttrack_badge_middle_large"/>
     
     <LinearLayout
         android:layout_width="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d1cb0bd..a1a179b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -396,6 +396,14 @@
         <attr name="spinnerItemStyle" format="reference" />
         <!-- Default MapView style. -->
         <attr name="mapViewStyle" format="reference" />
+        <!-- Dark Fasttrack badge style. -->
+        <attr name="fasttrackBadgeWidgetStyle" format="reference" />
+        <!-- Dark Fasttrack badge style with small fasttrack window. -->
+        <attr name="fasttrackBadgeWidgetStyleWindowSmall" format="reference" />
+        <!-- Dark Fasttrack badge style with medium fasttrack window. -->
+        <attr name="fasttrackBadgeWidgetStyleWindowMedium" format="reference" />
+        <!-- Dark Fasttrack badge style with large fasttrack window. -->
+        <attr name="fasttrackBadgeWidgetStyleWindowLarge" format="reference" />
 
         <!-- =================== -->
         <!-- Preference styles   -->
@@ -2197,6 +2205,14 @@
         <attr name="orientation" />
     </declare-styleable>
 
+    <declare-styleable name="FasttrackBadgeWidget">
+        <attr name="fasttrackWindowSize">
+            <enum name="modeSmall" value="1" />
+            <enum name="modeMedium" value="2" />
+            <enum name="modeLarge" value="3" />
+        </attr>
+    </declare-styleable>
+
     <!-- ======================================= -->
     <!-- Widget package parent layout attributes -->
     <!-- ======================================= -->
@@ -2843,9 +2859,7 @@
              is also used as an icon to the left of the search box and you cannot modify this
              behavior, so including the icon attribute is unecessary and this may be
              deprecated in the future.
-             <i>Optional attribute.</i>
-             {@deprecated This will create a non-standard UI appearance, because the search bar UI
-              now puts the activity or application icon beside the search box.} -->
+             <i>Optional attribute.</i> -->
         <attr name="icon" />
         <!-- This is the user-displayed name of the searchable activity.  <i>Required
             attribute.</i> -->
@@ -2870,10 +2884,7 @@
           <flag name="showSearchLabelAsBadge" value="0x04" />
           <!-- If set, this flag enables the display of the search target (icon) within the
                search bar.  (Note, overrides showSearchLabel)  If neither bad mode is selected,
-               no badge will be shown.
-              {@deprecated This will create a non-standard UI appearance, because the search bar UI
-              now puts the activity or application icon beside the search box.}
-               -->
+               no badge will be shown.-->
           <flag name="showSearchIconAsBadge" value="0x08" />
           <!-- If set, this flag causes the suggestion column SUGGEST_COLUMN_INTENT_DATA to
                be considered as the text for suggestion query rewriting.  This should only
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0902c21..69ddd63 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -234,7 +234,7 @@
     supply an auth token without prompting the user to re-enter the
     password.  This is the text that will scroll through the
     notification bar (will be seen by the user as he uses another application). -->
-    <string name="notification_title">Sign-in error</string>
+    <string name="notification_title">Sign-in error for <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g></string>
 
     <!-- Sync notifications --> <skip />
     <!-- A notification is shown when there is a sync error.  This is the text that will scroll through the notification bar (will be seen by the user as he uses another application). -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a2ceb8f..fae612c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -517,6 +517,26 @@
         <item name="android:shadowRadius">2.75</item>
     </style>
 
+    <style name="Widget.FasttrackBadgeWidget">
+        <item name="android:layout_width">48dip</item>
+        <item name="android:layout_height">52dip</item>
+        <item name="android:background">@android:drawable/fasttrack_badge_dark</item>
+        <item name="android:clickable">true</item>
+        <item name="android:scaleType">fitCenter</item>
+    </style>
+
+    <style name="Widget.FasttrackBadgeWidget.WindowSmall">
+        <item name="android:fasttrackWindowSize">modeSmall</item>
+    </style>
+
+    <style name="Widget.FasttrackBadgeWidget.WindowMedium">
+        <item name="android:fasttrackWindowSize">modeMedium</item>
+    </style>
+
+    <style name="Widget.FasttrackBadgeWidget.WindowLarge">
+        <item name="android:fasttrackWindowSize">modeLarge</item>
+    </style>
+
     <!-- Text Appearances -->
     <eat-comment />
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3b9590d..4f76c56 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -176,6 +176,9 @@
         <item name="spinnerItemStyle">@android:style/Widget.TextView.SpinnerItem</item>
         <item name="dropDownHintAppearance">@android:style/TextAppearance.Widget.DropDownHint</item>
         <item name="keyboardViewStyle">@android:style/Widget.KeyboardView</item>
+        <item name="fasttrackBadgeWidgetStyleWindowSmall">@android:style/Widget.FasttrackBadgeWidget.WindowSmall</item>
+        <item name="fasttrackBadgeWidgetStyleWindowMedium">@android:style/Widget.FasttrackBadgeWidget.WindowMedium</item>
+        <item name="fasttrackBadgeWidgetStyleWindowLarge">@android:style/Widget.FasttrackBadgeWidget.WindowLarge</item>
         
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@android:style/Preference.PreferenceScreen</item>
diff --git a/docs/html/guide/topics/resources/available-resources.jd b/docs/html/guide/topics/resources/available-resources.jd
index 0dfc625..f5f1475 100644
--- a/docs/html/guide/topics/resources/available-resources.jd
+++ b/docs/html/guide/topics/resources/available-resources.jd
@@ -908,7 +908,7 @@
 </p>
 <pre>
 &lt;<em>ViewGroupClass</em> xmlns:android="http://schemas.android.com/apk/res/android"
-                id="@+id/<em>string_name</em>" (attributes)&gt;
+                android:id="@+id/<em>string_name</em>" (attributes)&gt;
    &lt;<em>widget</em> or other nested <em>ViewGroupClass</em>&gt;+
    &lt;requestFocus/&gt;(0 or 1 per layout file, assigned to any element)
 &lt;/<em>ViewGroupClass</em>&gt;
@@ -919,7 +919,7 @@
     </dt>
     <dd>
         <p>The file must have a single root element. This can be a ViewGroup class that contains other elements, or a widget (or custom item) if it's only one object. By default, you can use any (case-sensitive) Android {@link android.widget widget} or {@link android.view.ViewGroup ViewGroup} class name as an element. These elements support attributes that apply to the underlying class, but the naming is not as clear. How to discover what attributes are supported for what tags is discussed below. You should not assume that any nesting is valid (for example you cannot enclose <code>&lt;TextView&gt;</code> elements inside a <code>&lt;ListLayout&gt;</code>).</p>
-        <p>If a class derives from another class, the XML element inherits all the attributes from the element that it "derives" from. So, for example, <code>&lt;EditText&gt;</code> is the corresponding XML element for the EditText class. It exposes its own unique attributes (<code>EditText_numeric</code>), as well as all attributes supported by <code>&lt;TextView&gt;</code> and <code>&lt;View&gt;</code>. For the <em>id</em> attribute of a tag in XML, you should use a special syntax: "@+id/<em>somestringvalue</em>". The "@+" syntax creates a resource number in the R.id class, if one doesn't exist, or uses it, if it does exist. When declaring an ID value for an XML tag, use this syntax. Example: <code>&lt;TextView id="@+id/nameTextbox"/&gt;</code>, and refer to it this way in Java: <code>findViewById(R.id.nameTextbox)</code>. All elements support the following values:</p>
+        <p>If a class derives from another class, the XML element inherits all the attributes from the element that it "derives" from. So, for example, <code>&lt;EditText&gt;</code> is the corresponding XML element for the EditText class. It exposes its own unique attributes (<code>EditText_numeric</code>), as well as all attributes supported by <code>&lt;TextView&gt;</code> and <code>&lt;View&gt;</code>. For the <em>id</em> attribute of a tag in XML, you should use a special syntax: "@+id/<em>somestringvalue</em>". The "@+" syntax creates a resource number in the R.id class, if one doesn't exist, or uses it, if it does exist. When declaring an ID value for an XML tag, use this syntax. Example: <code>&lt;TextView android:id="@+id/nameTextbox"/&gt;</code>, and refer to it this way in Java: <code>findViewById(R.id.nameTextbox)</code>. All elements support the following values:</p>
         <ul>
             <li>
                 <em>id</em> - An ID value used to access this element in Java. Typically you will use the syntax @+id/<em>string_name</em> to generate an ID for you in the id.xml file if you haven't created one yourself.
@@ -1007,7 +1007,7 @@
              android:paddingBottom="4"            // TextView.paddingBottom
              android:text="@string/redirect_getter"/&gt; // TextView.text
 
-   &lt;EditText id="@+id/text"
+   &lt;EditText android:id="@+id/text"
              android:layout_width="fill_parent"   // EditText.LayoutParams.width
              android:layout_height="wrap_content" // EditText.LayoutParams.height
              android:layout_weight="0"            // EditText.LinearLayoutParams.weight
@@ -1015,7 +1015,7 @@
        &lt;requestFocus /&gt;
    &lt;/EditText&gt;
 
-   &lt;Button id="@+id/apply"
+   &lt;Button android:id="@+id/apply"
            android:layout_width="wrap_content"  // Button.LayoutParams.width
            android:layout_height="wrap_content" // Button.LayoutParams.height
            android:text="@string/apply" /&gt;      // TextView.text
@@ -1047,7 +1047,7 @@
         <strong>Java implementation file</strong> - The implementation file. The class must extend {@link android.view.View View} or a subclass. See LabelView.java in ApiDemos.
     </li>
     <li>
-        <strong>res/values/attrs.xml</strong> - Defines the XML element, and the attributes that it supports, for clients to use to instantiate your object in their layout XML file. Define your element in a <code>&lt;declare-styleable id=<em>your_java_class_name</em>&gt;</code>. See res/layout/attrs.xml in ApiDemos.
+        <strong>res/values/attrs.xml</strong> - Defines the XML element, and the attributes that it supports, for clients to use to instantiate your object in their layout XML file. Define your element in a <code>&lt;declare-styleable name=<em>your_java_class_name</em>&gt;</code>. See res/values/attrs.xml in ApiDemos.
     </li>
     <li>
         <strong>res/layout/<em>your_class</em>.xml</strong> [<em>optional</em>] - An optional XML file to describe the layout of your object. This could also be done in Java. See custom_view_1.xml in ApiDemos.
diff --git a/docs/html/sdk/1.0_r1/requirements.jd b/docs/html/sdk/1.0_r1/requirements.jd
index af06675..4163513 100644
--- a/docs/html/sdk/1.0_r1/requirements.jd
+++ b/docs/html/sdk/1.0_r1/requirements.jd
@@ -14,7 +14,13 @@
 <ul>
   <li>Windows XP or Vista</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h4>Supported Development Environments:</h4>
diff --git a/docs/html/sdk/1.0_r2/requirements.jd b/docs/html/sdk/1.0_r2/requirements.jd
index 74d90ef..4f7c093 100644
--- a/docs/html/sdk/1.0_r2/requirements.jd
+++ b/docs/html/sdk/1.0_r2/requirements.jd
@@ -13,7 +13,13 @@
 <ul>
   <li>Windows XP or Vista</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h4>Supported Development Environments:</h4>
diff --git a/docs/html/sdk/1.1_r1/requirements.jd b/docs/html/sdk/1.1_r1/requirements.jd
index 95b658b..9d8f9eb 100644
--- a/docs/html/sdk/1.1_r1/requirements.jd
+++ b/docs/html/sdk/1.1_r1/requirements.jd
@@ -11,7 +11,13 @@
 <ul>
   <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r1/requirements.jd b/docs/html/sdk/1.5_r1/requirements.jd
index 4ed38a7..c10ccac 100644
--- a/docs/html/sdk/1.5_r1/requirements.jd
+++ b/docs/html/sdk/1.5_r1/requirements.jd
@@ -7,7 +7,13 @@
 <ul>
   <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r2/requirements.jd b/docs/html/sdk/1.5_r2/requirements.jd
index 4ed38a7..c10ccac 100644
--- a/docs/html/sdk/1.5_r2/requirements.jd
+++ b/docs/html/sdk/1.5_r2/requirements.jd
@@ -7,7 +7,13 @@
 <ul>
   <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r3/requirements.jd b/docs/html/sdk/1.5_r3/requirements.jd
index 5f20cf1..5bcee27 100644
--- a/docs/html/sdk/1.5_r3/requirements.jd
+++ b/docs/html/sdk/1.5_r3/requirements.jd
@@ -10,7 +10,13 @@
 <ul>
   <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.6_r1/index.jd b/docs/html/sdk/1.6_r1/index.jd
index 419649e..8f33949 100644
--- a/docs/html/sdk/1.6_r1/index.jd
+++ b/docs/html/sdk/1.6_r1/index.jd
@@ -5,16 +5,16 @@
 sdk.date=September 2009
 
 sdk.win_download=android-sdk-windows-1.6_r1.zip
-sdk.win_bytes=251325064
-sdk.win_checksum=efd6fccd5a6ff6b57585b49393d221d9
+sdk.win_bytes=260529085
+sdk.win_checksum=2bcbacbc7af0363058ca1cac6abad848
 
 sdk.mac_download=android-sdk-mac_x86-1.6_r1.zip
-sdk.mac_bytes=238229779
-sdk.mac_checksum=2be1a1ae5d33272be841c97e8a3a3b1c
+sdk.mac_bytes=247412515
+sdk.mac_checksum=eb13cc79602d492e89103efcf48ac1f6
 
 sdk.linux_download=android-sdk-linux_x86-1.6_r1.tgz
-sdk.linux_bytes=229032773
-sdk.linux_checksum=02ff0d0e38d4f464108a5a7f7567b207
+sdk.linux_bytes=238224860
+sdk.linux_checksum=b4bf0e610ff6db2fb6fb09c49cba1e79
 
 adt.zip_download=ADT-0.9.3.zip
 adt.zip_version=0.9.3
diff --git a/docs/html/sdk/1.6_r1/requirements.jd b/docs/html/sdk/1.6_r1/requirements.jd
index 8e698fa..8cfc049 100644
--- a/docs/html/sdk/1.6_r1/requirements.jd
+++ b/docs/html/sdk/1.6_r1/requirements.jd
@@ -11,7 +11,13 @@
 <ul>
   <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
   <li>Mac OS X 10.4.8 or later (x86 only)</li>
-  <li>Linux (tested on Linux Ubuntu Hardy Heron)</li>
+  <li>Linux (tested on Linux Ubuntu Hardy Heron)
+    <ul>
+      <li>64-bit distributions must be capable of running 32-bit applications. 
+      For information about how to add support for 32-bit applications, see
+      the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+    </ul>
+  </li>
 </ul>
 
 <h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index 130a92c..0dcafd3 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -24,6 +24,11 @@
 Devices</a> and download new SDK packages (such as platform versions and 
 add-ons) into your environment.</li>
     <li>Improved support for test packages in New Project Wizard</li>
+    <li>The reference documentation now offers a "Filter by API Level" 
+capability that lets you display only the parts of the API that are actually 
+available to your application, based on the <code>android:minSdkVersion</code>
+value the application declares in its manifest. For more information, see
+<a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li>
   </ul>
 
 <p>For details about the Android platforms included in the SDK &mdash; including
@@ -71,8 +76,8 @@
 
 <h3>Android SDK and AVD Manager</h3>
 
-<p>The SDK offers a new tool called Android AVD Manager that lets you manage
-your SDK and AVD environments more efficiently. </p>
+<p>The SDK offers a new tool called Android SDK and AVD Manager that lets you 
+manage your SDK and AVD environments more efficiently. </p>
 
 <p>Using the tool, you can quickly check what Android platforms, add-ons,
 extras, and documentation packages are available in your SDK environment, what
@@ -181,7 +186,7 @@
 <p>Besides these defaults, You can also create an AVD that overrides the default
 density for each skin, to create any combination of resolution/density (WVGA
 with medium density, for instance).  To do so, use the <code>android</code> tool
-command line to create a new AVD that uses a custom hardare configuration. See
+command line to create a new AVD that uses a custom hardware configuration. See
 <a href="{@docRoot}guide/developing/tools/avd.html#createavd">Creating an
 AVD</a> for more information.</p>
 
diff --git a/docs/html/sdk/android-1.6-highlights.jd b/docs/html/sdk/android-1.6-highlights.jd
index 74dcd9f..b4a97d7 100644
--- a/docs/html/sdk/android-1.6-highlights.jd
+++ b/docs/html/sdk/android-1.6-highlights.jd
@@ -113,7 +113,7 @@
 <h3 id="A11y">Accessibility</h3>
 
 <p>Users will be able to download new accessibility services built
-on the new Accessibility framework and enable them in Settings.</p>
+on the new accessibility framework and enable them in Settings.</p>
 
 
 
diff --git a/graphics/java/android/graphics/BlurMaskFilter.java b/graphics/java/android/graphics/BlurMaskFilter.java
index dbf57ac..5eafe76 100644
--- a/graphics/java/android/graphics/BlurMaskFilter.java
+++ b/graphics/java/android/graphics/BlurMaskFilter.java
@@ -16,13 +16,19 @@
 
 package android.graphics;
 
+/**
+ * This takes a mask, and blurs its edge by the specified radius. Whether or
+ * or not to include the original mask, and whether the blur goes outside,
+ * inside, or straddles, the original mask's border, is controlled by the
+ * Blur enum.
+ */
 public class BlurMaskFilter extends MaskFilter {
 
     public enum Blur {
-        NORMAL(0),  //!< fuzzy inside and outside
-        SOLID(1),   //!< solid inside, fuzzy outside
-        OUTER(2),   //!< nothing inside, fuzzy outside
-        INNER(3);   //!< fuzzy inside, nothing outside
+        NORMAL(0),  //!< blur inside and outside of the original border
+        SOLID(1),   //!< include the original mask, blur outside
+        OUTER(2),   //!< just blur outside the original border
+        INNER(3);   //!< just blur inside the original border
         
         Blur(int value) {
             native_int = value;
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e82f297..f42788e 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -271,7 +271,8 @@
 
     public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) {
         final BitmapState state = mBitmapState;
-        if (state.mTileModeX != xmode || state.mTileModeY != ymode) {
+        if (state.mPaint.getShader() == null ||
+                state.mTileModeX != xmode || state.mTileModeY != ymode) {
             state.mTileModeX = xmode;
             state.mTileModeY = ymode;
             mRebuildShader = true;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 7749ad34..30c81ab 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -113,6 +113,10 @@
         mRS.nAllocationSubDataFromObject(mID, mType, 0, o);
     }
 
+    public void read(Object o) {
+        mRS.nAllocationSubReadFromObject(mID, mType, 0, o);
+    }
+
     public void subData(int offset, Object o) {
         mRS.nAllocationSubDataFromObject(mID, mType, offset, o);
     }
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 6f5b67e..89db4fa 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -106,6 +106,7 @@
     native void nAllocationRead(int id, int[] d);
     native void nAllocationRead(int id, float[] d);
     native void nAllocationSubDataFromObject(int id, Type t, int offset, Object o);
+    native void nAllocationSubReadFromObject(int id, Type t, int offset, Object o);
 
     native void nTriangleMeshBegin(int vertex, int index);
     native void nTriangleMeshAddVertex_XY (float x, float y);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index a94ccb1..90b5958 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -253,10 +253,39 @@
     return ((uint8_t *)buffer) + 4;
 }
 
+static void * SF_SaveInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    LOGE("Save Int");
+    _env->SetIntField(_obj, _field, ((int32_t *)buffer)[0]);
+    return ((uint8_t *)buffer) + 4;
+}
+
+static void * SF_SaveShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    LOGE("Save Short");
+    _env->SetShortField(_obj, _field, ((int16_t *)buffer)[0]);
+    return ((uint8_t *)buffer) + 2;
+}
+
+static void * SF_SaveByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    LOGE("Save Byte");
+    _env->SetByteField(_obj, _field, ((int8_t *)buffer)[0]);
+    return ((uint8_t *)buffer) + 1;
+}
+
+static void * SF_SaveFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    LOGE("Save Float");
+    _env->SetFloatField(_obj, _field, ((float *)buffer)[0]);
+    return ((uint8_t *)buffer) + 4;
+}
+
 struct TypeFieldCache {
     jfieldID field;
     int bits;
     void * (*ptr)(JNIEnv *, jobject, jfieldID, void *buffer);
+    void * (*readPtr)(JNIEnv *, jobject, jfieldID, void *buffer);
 };
 
 struct TypeCache {
@@ -296,13 +325,23 @@
         switch(fType[ct]) {
         case RS_TYPE_FLOAT:
             tfc[ct].ptr = SF_LoadFloat;
+            tfc[ct].readPtr = SF_SaveFloat;
             break;
         case RS_TYPE_UNSIGNED:
         case RS_TYPE_SIGNED:
             switch(tfc[ct].bits) {
-            case 32:    tfc[ct].ptr = SF_LoadInt;   break;
-            case 16:    tfc[ct].ptr = SF_LoadShort; break;
-            case 8:     tfc[ct].ptr = SF_LoadByte;  break;
+            case 32:
+                tfc[ct].ptr = SF_LoadInt;
+                tfc[ct].readPtr = SF_SaveInt;
+                break;
+            case 16:
+                tfc[ct].ptr = SF_LoadShort;
+                tfc[ct].readPtr = SF_SaveShort;
+                break;
+            case 8:
+                tfc[ct].ptr = SF_LoadByte;
+                tfc[ct].readPtr = SF_SaveByte;
+                break;
             }
             break;
         }
@@ -545,7 +584,30 @@
         buf = tfc->ptr(_env, _o, tfc->field, buf);
     }
     rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
-    const uint32_t * tmp = (const uint32_t *)bufAlloc;
+    free(bufAlloc);
+}
+
+static void
+nAllocationSubReadFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationReadFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
+
+    assert(offset == 0);
+
+    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
+
+    void * bufAlloc = malloc(tc->size);
+    void * buf = bufAlloc;
+    rsAllocationRead(con, (RsAllocation)alloc, bufAlloc);
+
+    LOGE("size %i, ", tc->size);
+
+    for (int ct=0; ct < tc->fieldCount; ct++) {
+        const TypeFieldCache *tfc = &tc->fields[ct];
+        LOGE("ct=%i, buf=%p", ct, buf);
+        buf = tfc->readPtr(_env, _o, tfc->field, buf);
+    }
     free(bufAlloc);
 }
 
@@ -1270,6 +1332,7 @@
 {"nAllocationRead",                "(I[I)V",                               (void*)nAllocationRead_i },
 {"nAllocationRead",                "(I[F)V",                               (void*)nAllocationRead_f },
 {"nAllocationSubDataFromObject",   "(ILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubDataFromObject },
+{"nAllocationSubReadFromObject",   "(ILandroid/renderscript/Type;ILjava/lang/Object;)V",   (void*)nAllocationSubReadFromObject },
 
 {"nTriangleMeshBegin",             "(II)V",                                (void*)nTriangleMeshBegin },
 {"nTriangleMeshAddVertex_XY",      "(FF)V",                                (void*)nTriangleMeshAddVertex_XY },
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 0014d5c..10e0197 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -25,6 +25,8 @@
 #include <OMX_Core.h>
 #include <OMX_Video.h>
 
+#include "jni.h"
+
 namespace android {
 
 class IMemory;
@@ -102,15 +104,22 @@
             size_t encodedWidth, size_t encodedHeight,
             size_t displayWidth, size_t displayHeight) = 0;
 
-    // Note: This method is _not_ virtual, it exists as a wrapper around
+    // Note: These methods are _not_ virtual, it exists as a wrapper around
     // the virtual "createRenderer" method above facilitating extraction
-    // of the ISurface from a regular Surface.
+    // of the ISurface from a regular Surface or a java Surface object.
     sp<IOMXRenderer> createRenderer(
             const sp<Surface> &surface,
             const char *componentName,
             OMX_COLOR_FORMATTYPE colorFormat,
             size_t encodedWidth, size_t encodedHeight,
             size_t displayWidth, size_t displayHeight);
+
+    sp<IOMXRenderer> createRendererFromJavaSurface(
+            JNIEnv *env, jobject javaSurface,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            size_t encodedWidth, size_t encodedHeight,
+            size_t displayWidth, size_t displayHeight);
 };
 
 struct omx_message {
diff --git a/include/media/stagefright/SoftwareRenderer.h b/include/media/stagefright/SoftwareRenderer.h
index 705b914..b61858c 100644
--- a/include/media/stagefright/SoftwareRenderer.h
+++ b/include/media/stagefright/SoftwareRenderer.h
@@ -18,6 +18,7 @@
 
 #define SOFTWARE_RENDERER_H_
 
+#include <OMX_Video.h>
 #include <media/stagefright/VideoRenderer.h>
 #include <utils/RefBase.h>
 
@@ -29,6 +30,7 @@
 class SoftwareRenderer : public VideoRenderer {
 public:
     SoftwareRenderer(
+            OMX_COLOR_FORMATTYPE colorFormat,
             const sp<ISurface> &surface,
             size_t displayWidth, size_t displayHeight,
             size_t decodedWidth, size_t decodedHeight);
@@ -39,6 +41,12 @@
             const void *data, size_t size, void *platformPrivate);
 
 private:
+    uint8_t *initClip();
+
+    void renderCbYCrY(const void *data, size_t size);
+    void renderYUV420Planar(const void *data, size_t size);
+
+    OMX_COLOR_FORMATTYPE mColorFormat;
     sp<ISurface> mISurface;
     size_t mDisplayWidth, mDisplayHeight;
     size_t mDecodedWidth, mDecodedHeight;
@@ -46,6 +54,8 @@
     sp<MemoryHeapBase> mMemoryHeap;
     int mIndex;
 
+    uint8_t *mClip;
+
     SoftwareRenderer(const SoftwareRenderer &);
     SoftwareRenderer &operator=(const SoftwareRenderer &);
 };
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 118fb83..2cedeb6 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -212,7 +212,7 @@
 
     
     void setUsage(uint32_t reqUsage);
-    bool getUsage(uint32_t* usage);
+    uint32_t getUsage() const;
     
     // constants
     sp<SurfaceComposerClient>   mClient;
@@ -227,7 +227,6 @@
     // protected by mSurfaceLock
     Rect                        mSwapRectangle;
     uint32_t                    mUsage;
-    int32_t                     mUsageChanged;
     
     // protected by mSurfaceLock. These are also used from lock/unlock
     // but in that case, they must be called form the same thread.
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index c3fbea2..4dab3a2 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -361,7 +361,6 @@
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
     // be default we request a hardware surface
     mUsage = GRALLOC_USAGE_HW_RENDER;
-    mUsageChanged = true;
     mNeedFullUpdate = false;
 }
 
@@ -499,13 +498,12 @@
         return bufIdx;
     }
     
-    // FIXME: in case of failure below, we need to undo the dequeue
-    
-    uint32_t usage;
-    const bool usageChanged = getUsage(&usage);
+    const uint32_t usage(getUsage());
     const sp<SurfaceBuffer>& backBuffer(mBuffers[bufIdx]);
-    if ((backBuffer == 0) || usageChanged || 
-            mSharedBufferClient->needNewBuffer(bufIdx)) {
+    if (backBuffer == 0 || 
+        uint32_t(backBuffer->usage) != usage ||
+        mSharedBufferClient->needNewBuffer(bufIdx)) 
+    {
         err = getBufferLocked(bufIdx, usage);
         LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
                 bufIdx, usage, strerror(-err));
@@ -600,21 +598,13 @@
 void Surface::setUsage(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mSurfaceLock);
-    if (mUsage != reqUsage) {
-        mUsageChanged = true;
-        mUsage = reqUsage;
-    }
+    mUsage = reqUsage;
 }
 
-bool Surface::getUsage(uint32_t* usage)
+uint32_t Surface::getUsage() const
 {
     Mutex::Autolock _l(mSurfaceLock);
-    *usage = mUsage;
-    if (mUsageChanged) {
-        mUsageChanged = false;
-        return true;
-    }
-    return false;
+    return mUsage;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 9d442c3..7c01687 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -37,6 +37,7 @@
 endif
 
 LOCAL_C_INCLUDES := \
+	$(JNI_H_INCLUDE) \
 	$(call include-path-for, graphics corecg) \
         $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
 
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 10bebd0..0cec7bb 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -45,6 +45,31 @@
             displayWidth, displayHeight);
 }
 
+sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
+        JNIEnv *env, jobject javaSurface,
+        const char *componentName,
+        OMX_COLOR_FORMATTYPE colorFormat,
+        size_t encodedWidth, size_t encodedHeight,
+        size_t displayWidth, size_t displayHeight) {
+    jclass surfaceClass = env->FindClass("android/view/Surface");
+    if (surfaceClass == NULL) {
+        LOGE("Can't find android/view/Surface");
+        return NULL;
+    }
+
+    jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
+    if (surfaceID == NULL) {
+        LOGE("Can't find Surface.mSurface");
+        return NULL;
+    }
+
+    sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID);
+
+    return createRenderer(
+            surface, componentName, colorFormat, encodedWidth,
+            encodedHeight, displayWidth, displayHeight);
+}
+
 class BpOMX : public BpInterface<IOMX> {
 public:
     BpOMX(const sp<IBinder> &impl)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 93b7a3a..f21eb73 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -47,6 +47,7 @@
 endif
 
 LOCAL_C_INCLUDES := external/tremor/Tremor                              \
+	$(JNI_H_INCLUDE)                                                \
 	$(call include-path-for, graphics corecg)                       \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
 	$(TOP)/frameworks/base/media/libstagefright/omx
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 79a32b5..3c343a3 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -38,6 +38,7 @@
 endif
 
 LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
         $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
         $(TOP)/external/opencore/android
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 22c2f39..ba4c4c7 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -229,6 +229,7 @@
     }
     if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
         // XXX Required on P....on only.
+        quirks |= kRequiresAllocateBufferOnInputPorts;
         quirks |= kRequiresAllocateBufferOnOutputPorts;
     }
 
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 77e42be..4cadccd 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_CFLAGS := $(PV_CFLAGS_MINUS_VISIBILITY)
 
 LOCAL_C_INCLUDES += $(TOP)/hardware/ti/omap3/liboverlay
+LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)
 
 LOCAL_SRC_FILES:=                 \
 	OMX.cpp                   \
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 1e59b52..8b83dd6 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -609,6 +609,7 @@
     } else {
         LOGW("Using software renderer.");
         impl = new SoftwareRenderer(
+                colorFormat,
                 surface,
                 displayWidth, displayHeight,
                 encodedWidth, encodedHeight);
diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
index da97d55..a1c478f 100644
--- a/media/libstagefright/omx/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -27,17 +27,20 @@
 #define QCOM_YUV        0
 
 SoftwareRenderer::SoftwareRenderer(
+        OMX_COLOR_FORMATTYPE colorFormat,
         const sp<ISurface> &surface,
         size_t displayWidth, size_t displayHeight,
         size_t decodedWidth, size_t decodedHeight)
-    : mISurface(surface),
+    : mColorFormat(colorFormat),
+      mISurface(surface),
       mDisplayWidth(displayWidth),
       mDisplayHeight(displayHeight),
       mDecodedWidth(decodedWidth),
       mDecodedHeight(decodedHeight),
       mFrameSize(mDecodedWidth * mDecodedHeight * 2),  // RGB565
       mMemoryHeap(new MemoryHeapBase(2 * mFrameSize)),
-      mIndex(0) {
+      mIndex(0),
+      mClip(NULL) {
     CHECK(mISurface.get() != NULL);
     CHECK(mDecodedWidth > 0);
     CHECK(mDecodedHeight > 0);
@@ -55,29 +58,37 @@
 
 SoftwareRenderer::~SoftwareRenderer() {
     mISurface->unregisterBuffers();
+
+    delete[] mClip;
+    mClip = NULL;
 }
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    switch (mColorFormat) {
+        case OMX_COLOR_FormatYUV420Planar:
+            return renderYUV420Planar(data, size);
+
+        case OMX_COLOR_FormatCbYCrY:
+            return renderCbYCrY(data, size);
+
+        default:
+        {
+            LOGW("Cannot render color format %ld", mColorFormat);
+            break;
+        }
+    }
+}
+
+void SoftwareRenderer::renderYUV420Planar(
+        const void *data, size_t size) {
     if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
         LOGE("size is %d, expected %d",
                 size, (mDecodedHeight * mDecodedWidth * 3) / 2);
     }
     CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
 
-    static const signed kClipMin = -278;
-    static const signed kClipMax = 535;
-    static uint8_t kClip[kClipMax - kClipMin + 1];
-    static uint8_t *kAdjustedClip = &kClip[-kClipMin];
-
-    static bool clipInitialized = false;
-
-    if (!clipInitialized) {
-        for (signed i = kClipMin; i <= kClipMax; ++i) {
-            kClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i;
-        }
-        clipInitialized = true;
-    }
+    uint8_t *kAdjustedClip = initClip();
 
     size_t offset = mIndex * mFrameSize;
 
@@ -172,4 +183,78 @@
     mIndex = 1 - mIndex;
 }
 
+void SoftwareRenderer::renderCbYCrY(
+        const void *data, size_t size) {
+    if (size != (mDecodedHeight * mDecodedWidth * 2)) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 2));
+    }
+    CHECK(size >= (mDecodedWidth * mDecodedHeight * 2));
+
+    uint8_t *kAdjustedClip = initClip();
+
+    size_t offset = mIndex * mFrameSize;
+    void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+    uint32_t *dst_ptr = (uint32_t *)dst;
+
+    const uint8_t *src = (const uint8_t *)data;
+
+    for (size_t y = 0; y < mDecodedHeight; ++y) {
+        for (size_t x = 0; x < mDecodedWidth; x += 2) {
+            signed y1 = (signed)src[2 * x + 1] - 16;
+            signed y2 = (signed)src[2 * x + 3] - 16;
+            signed u = (signed)src[2 * x] - 128;
+            signed v = (signed)src[2 * x + 2] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[r1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[b1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[r2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[b2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src += mDecodedWidth * 2;
+        dst_ptr += mDecodedWidth / 2;
+    }
+
+    mISurface->postBuffer(offset);
+    mIndex = 1 - mIndex;
+}
+
+uint8_t *SoftwareRenderer::initClip() {
+    static const signed kClipMin = -278;
+    static const signed kClipMax = 535;
+
+    if (mClip == NULL) {
+        mClip = new uint8_t[kClipMax - kClipMin + 1];
+
+        for (signed i = kClipMin; i <= kClipMax; ++i) {
+            mClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i;
+        }
+    }
+
+    return &mClip[-kClipMin];
+}
+
 }  // namespace android
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
new file mode 100644
index 0000000..0401390
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -0,0 +1,84 @@
+package com.android.mediaframeworktest;
+
+import android.media.MediaRecorder;
+import android.os.SystemProperties;
+import java.util.HashMap;
+
+public class MediaProfileReader {
+
+    public static final HashMap<String, Integer>
+    OUTPUT_FORMAT_TABLE = new HashMap<String, Integer>();
+    public static String MEDIA_ENC_VID = "ro.media.enc.vid.";
+    public static String MEDIA_AUD_VID = "ro.media.enc.aud.";
+    public static String[] VIDEO_ENCODER_PROPERTY = {".width", ".height", ".bps", ".fps",};
+    public static String[] AUDIO_ENCODER_PROPERTY = {".bps", ".hz", ".ch",};
+
+    public static String getVideoCodecProperty() {
+        String s;
+        s = SystemProperties.get("ro.media.enc.vid.codec");
+        return s;
+    }
+
+    public static String getAudioCodecProperty() {
+        String s;
+        s = SystemProperties.get("ro.media.enc.aud.codec");
+        return s;
+    }
+
+    public static String getDeviceType() {
+        // push all the property into one big table
+        String s;
+        s = SystemProperties.get("ro.product.name");
+        return s;
+    }
+
+    public static void createVideoProfileTable() {
+        // push all the property into one big table
+        String encoderType = getVideoCodecProperty();
+        String encoder[] = encoderType.split(",");
+        for (int i = 0; i < encoder.length; i++) {
+            for (int j = 0; j < VIDEO_ENCODER_PROPERTY.length; j++) {
+                String propertyName = MEDIA_ENC_VID + encoder[i] + VIDEO_ENCODER_PROPERTY[j];
+                String prop = SystemProperties.get(propertyName);
+                //push to the table
+                String propRange[] = prop.split(",");
+                OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_low"),
+                        Integer.parseInt(propRange[0]));
+                OUTPUT_FORMAT_TABLE.put((encoder[i] + VIDEO_ENCODER_PROPERTY[j] + "_high"),
+                        Integer.parseInt(propRange[1]));
+            }
+
+        }
+    }
+
+    public static void createAudioProfileTable() {
+        // push all the property into one big table
+        String audioType = getAudioCodecProperty();
+        String encoder[] = audioType.split(",");
+        for (int i = 0; i < encoder.length; i++) {
+            for (int j = 0; j < AUDIO_ENCODER_PROPERTY.length; j++) {
+                String propertyName = MEDIA_AUD_VID + encoder[i] + AUDIO_ENCODER_PROPERTY[j];
+                String prop = SystemProperties.get(propertyName);
+                //push to the table
+                String propRange[] = prop.split(",");
+                OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_low"),
+                        Integer.parseInt(propRange[0]));
+                OUTPUT_FORMAT_TABLE.put((encoder[i] + AUDIO_ENCODER_PROPERTY[j] + "_high"),
+                        Integer.parseInt(propRange[1]));
+            }
+
+        }
+    }
+
+    public static void createEncoderTable(){
+        OUTPUT_FORMAT_TABLE.put("h263", MediaRecorder.VideoEncoder.H263);
+        OUTPUT_FORMAT_TABLE.put("h264", MediaRecorder.VideoEncoder.H264);
+        OUTPUT_FORMAT_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP);
+        OUTPUT_FORMAT_TABLE.put("amrnb", MediaRecorder.AudioEncoder.AMR_NB);
+        OUTPUT_FORMAT_TABLE.put("amrwb", MediaRecorder.AudioEncoder.AMR_WB);
+        OUTPUT_FORMAT_TABLE.put("aac", MediaRecorder.AudioEncoder.AAC);
+        OUTPUT_FORMAT_TABLE.put("aacplus", MediaRecorder.AudioEncoder.AAC_PLUS);
+        OUTPUT_FORMAT_TABLE.put("eaacplus",
+                MediaRecorder.AudioEncoder.EAAC_PLUS);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index ef0a3b1..39846c6 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -29,7 +29,7 @@
 import android.util.Log;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
-
+import com.android.mediaframeworktest.MediaProfileReader;
 
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.Suppress;
@@ -46,6 +46,9 @@
     
     private SurfaceHolder mSurfaceHolder = null;
     private MediaRecorder mRecorder;
+
+    private int MIN_VIDEO_FPS = 5;
+
     Context mContext;
     Camera mCamera;
   
@@ -96,7 +99,70 @@
         }
     }
     
-    
+    private boolean recordVideoWithPara(String encoder, String audio, String quality){
+        boolean recordSuccess = false;
+        int videoEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder);
+        int audioEncoder = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio);
+        int videoWidth = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".width_" + quality);
+        int videoHeight =
+                MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".height_" + quality);
+        int videoFps = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".fps_" + quality);
+        int videoBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(encoder + ".bps_" + quality);
+        int audioBitrate = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".bps_" + quality);
+        int audioChannels = MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".ch_" + quality);
+        int audioSamplingRate =
+                MediaProfileReader.OUTPUT_FORMAT_TABLE.get(audio + ".hz_" + quality);
+
+        if (videoFps < MIN_VIDEO_FPS) {
+            videoFps = MIN_VIDEO_FPS;
+        }
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        String filename = ("/sdcard/" + encoder + "_" + audio + "_" + quality + ".3gp");
+        try {
+            Log.v(TAG, "video encoder :" + videoEncoder);
+            Log.v(TAG, "audio encoder :" + audioEncoder);
+            Log.v(TAG, "quality : " + quality);
+            Log.v(TAG, "encoder : " + encoder);
+            Log.v(TAG, "audio : " + audio);
+            Log.v(TAG, "videoWidth : " + videoWidth);
+            Log.v(TAG, "videoHeight : " + videoHeight);
+            Log.v(TAG, "videoFPS : " + videoFps);
+            Log.v(TAG, "videobitrate : " + videoBitrate);
+            Log.v(TAG, "audioBitrate : " + audioBitrate);
+            Log.v(TAG, "audioChannel : " + audioChannels);
+            Log.v(TAG, "AudioSampleRate : " + audioSamplingRate);
+
+            MediaRecorder mMediaRecorder = new MediaRecorder();
+            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+            mMediaRecorder.setOutputFile(filename);
+            mMediaRecorder.setVideoFrameRate(videoFps);
+            mMediaRecorder.setVideoSize(videoWidth, videoHeight);
+            mMediaRecorder.setParameters(String.format("video-param-encoding-bitrate=%d",
+                    videoBitrate));
+            mMediaRecorder.setParameters(String.format("audio-param-encoding-bitrate=%d",
+                    audioBitrate));
+            mMediaRecorder.setParameters(String.format("audio-param-number-of-channels=%d",
+                    audioChannels));
+            mMediaRecorder.setParameters(String.format("audio-param-sampling-rate=%d",
+                    audioSamplingRate));
+            mMediaRecorder.setVideoEncoder(videoEncoder);
+            mMediaRecorder.setAudioEncoder(audioEncoder);
+            mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+            mMediaRecorder.prepare();
+            mMediaRecorder.start();
+            Thread.sleep(MediaNames.RECORDED_TIME);
+            mMediaRecorder.stop();
+            mMediaRecorder.release();
+            recordSuccess = validateVideo(filename, videoWidth, videoHeight);
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+            return false;
+        }
+        return recordSuccess;
+    }
+
     private boolean invalidRecordSetting(int frameRate, int width, int height, 
             int videoFormat, int outFormat, String outFile, boolean videoOnly) {
         try {
@@ -356,6 +422,35 @@
                MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false);      
         assertTrue("Invalid FrameRate", isTestInvalidFrameRateSuccessful);
     }
-    
+
+    @LargeTest
+    //est cases for the new codec
+    public void testDeviceSpecificCodec() throws Exception {
+        boolean recordSuccess = false;
+        String deviceType = MediaProfileReader.getDeviceType();
+        Log.v(TAG, "deviceType = " + deviceType);
+        if (deviceType.compareTo("voles") == 0) {
+            // Test cases are device specified
+            MediaProfileReader.createVideoProfileTable();
+            MediaProfileReader.createAudioProfileTable();
+            MediaProfileReader.createEncoderTable();
+            String encoderType = MediaProfileReader.getVideoCodecProperty();
+            String encoder[] = encoderType.split(",");
+            String audioType = MediaProfileReader.getAudioCodecProperty();
+            String audio[] = audioType.split(",");
+            for (int k = 0; k < 2; k++) {
+                for (int i = 0; i < encoder.length; i++) {
+                    for (int j = 0; j < audio.length; j++) {
+                        if (k == 0) {
+                            recordSuccess = recordVideoWithPara(encoder[i], audio[j], "high");
+                        } else {
+                            recordSuccess = recordVideoWithPara(encoder[i], audio[j], "low");
+                        }
+                        assertTrue((encoder[i] + audio[j]), recordSuccess);
+                    }
+                }
+            }
+        }
+    }
 }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index b13883e..39084a7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -27,7 +27,7 @@
 import android.content.res.Configuration;
 import android.location.LocationManager;
 import android.media.AudioManager;
-import android.os.IHardwareService;
+import android.os.IPowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
@@ -94,10 +94,10 @@
 
     private void setBrightness(int brightness) {
         try {
-            IHardwareService hardware = IHardwareService.Stub
-                    .asInterface(ServiceManager.getService("hardware"));
-            if (hardware != null) {
-                hardware.setBacklights(brightness);
+            IPowerManager power = IPowerManager.Stub.asInterface(
+                    ServiceManager.getService("power"));
+            if (power != null) {
+                power.setBacklightBrightness(brightness);
             }
         } catch (RemoteException doe) {
 
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 73853595..30c25e0 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
 import android.os.UEventObserver;
 import android.util.Log;
 
@@ -41,8 +42,11 @@
 
     private final Context mContext;
 
-    public DockObserver(Context context) {
+    private PowerManagerService mPowerManager;
+
+    public DockObserver(Context context, PowerManagerService pm) {
         mContext = context;
+        mPowerManager = pm;
         init();  // set initial status
         startObserving(DOCK_UEVENT_MATCH);
     }
@@ -103,6 +107,7 @@
             synchronized (this) {
                 Log.d(TAG, "Broadcasting dock state " + mDockState);
                 // Pack up the values and broadcast them to everyone
+                mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
                 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
                 intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
                 mContext.sendStickyBroadcast(intent);
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 01daae3..29c13e0 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -269,26 +269,6 @@
         Hardware.enableCameraFlash(milliseconds);
     }
 
-    public void setBacklights(int brightness) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        // Don't let applications turn the screen all the way off
-        brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
-        setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
-        setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
-        setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
-        long identity = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.noteScreenBrightness(brightness);
-        } catch (RemoteException e) {
-            Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     void setLightOff_UNCHECKED(int light) {
         setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0);
     }
@@ -307,14 +287,6 @@
         setLight_native(mNativePointer, light, color, mode, onMS, offMS);
     }
 
-    public void setAutoBrightness(boolean on) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        setAutoBrightness_UNCHECKED(on);
-    }
-
     void setAutoBrightness_UNCHECKED(boolean on) {
         if (mAutoBrightnessAvailable) {
             setAutoBrightness_native(mNativePointer, on);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 2951384..35f508b8 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2061,6 +2061,42 @@
         return result;
     }
 
+    public void setBacklightBrightness(int brightness) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+        // Don't let applications turn the screen all the way off
+        brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
+        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness);
+        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, brightness);
+        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness);
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteScreenBrightness(brightness);
+        } catch (RemoteException e) {
+            Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        // update our animation state
+        if (ANIMATE_SCREEN_LIGHTS) {
+            mScreenBrightness.curValue = brightness;
+            mScreenBrightness.animating = false;
+        }
+        if (ANIMATE_KEYBOARD_LIGHTS) {
+            mKeyboardBrightness.curValue = brightness;
+            mKeyboardBrightness.animating = false;
+        }
+        if (ANIMATE_BUTTON_LIGHTS) {
+            mButtonBrightness.curValue = brightness;
+            mButtonBrightness.animating = false;
+        }
+    }
+
+    public void setAutoBrightness(boolean on) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+        mHardware.setAutoBrightness_UNCHECKED(on);
+    }
+
     private SensorManager getSensorManager() {
         if (mSensorManager == null) {
             mSensorManager = new SensorManager(mHandlerThread.getLooper());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7c2a7ac..b3b50e5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -330,7 +330,7 @@
             try {
                 Log.i(TAG, "Dock Observer");
                 // Listen for dock station changes
-                dock = new DockObserver(context);
+                dock = new DockObserver(context, power);
             } catch (Throwable e) {
                 Log.e(TAG, "Failure starting DockObserver", e);
             }
diff --git a/telephony/java/com/android/internal/telephony/SmsResponse.java b/telephony/java/com/android/internal/telephony/SmsResponse.java
index bd79e02..a7c2840 100644
--- a/telephony/java/com/android/internal/telephony/SmsResponse.java
+++ b/telephony/java/com/android/internal/telephony/SmsResponse.java
@@ -37,4 +37,12 @@
         this.ackPdu = ackPdu;
         this.errorCode = errorCode;
     }
+
+    public String toString() {
+        String ret = "{ messageRef = " + messageRef
+                        + ", errorCode = " + errorCode
+                        + ", ackPdu = " + ackPdu
+                        + "}";
+        return ret;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index 806c31d..5bf1a0f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -436,7 +436,9 @@
             voiceCallStartedRegistrants.notifyRegistrants (
                     new AsyncResult(null, null, null));
         }
-
+        if (Phone.DEBUG_PHONE) {
+            log("update phone state, old= , new= , " + oldState + state);
+        }
         if (state != oldState) {
             phone.notifyPhoneStateChanged();
         }
@@ -519,27 +521,12 @@
                         return;
                     }
                 } else {
-                    connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
-
-                    // it's a ringing call
-                    if (connections[i].getCall() == ringingCall) {
-                        newRinging = connections[i];
-                    } else {
-                        // Something strange happened: a call appeared
-                        // which is neither a ringing call or one we created.
-                        // Either we've crashed and re-attached to an existing
-                        // call, or something else (eg, SIM) initiated the call.
-
-                        Log.i(LOG_TAG,"Phantom call appeared " + dc);
-
-                        // If it's a connected call, set the connect time so that
-                        // it's non-zero.  It may not be accurate, but at least
-                        // it won't appear as a Missed Call.
-                        if (dc.state != DriverCall.State.ALERTING
-                                && dc.state != DriverCall.State.DIALING) {
-                            connections[i].connectTime = System.currentTimeMillis();
-                        }
-
+                    if (Phone.DEBUG_PHONE) {
+                        log("pending Mo= , dc= " + pendingMO + dc);
+                    }
+                    // find if the MT call is a new ring or unknown connection
+                    newRinging = checkMtFindNewRinging(dc,i);
+                    if (newRinging == null) {
                         unknownConnectionAppeared = true;
                     }
                 }
@@ -571,9 +558,28 @@
                 // list but kept in the Call list
                 connections[i] = null;
             } else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */
-                boolean changed;
-                changed = conn.update(dc);
-                hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
+                // Call collision case
+                if (conn.isIncoming != dc.isMT) {
+                    if (dc.isMT == true){
+                        // Mt call takes precedence than Mo,drops Mo
+                        droppedDuringPoll.add(conn);
+                        // find if the MT call is a new ring or unknown connection
+                        newRinging = checkMtFindNewRinging(dc,i);
+                        if (newRinging == null) {
+                            unknownConnectionAppeared = true;
+                        }
+                    } else {
+                        // Call info stored in conn is not consistent with the call info from dc.
+                        // We should follow the rule of MT calls taking precedence over MO calls
+                        // when there is conflict, so here we drop the call info from dc and
+                        // continue to use the call info from conn, and only take a log.
+                        Log.e(LOG_TAG,"Error in RIL, Phantom call appeared " + dc);
+                    }
+                } else {
+                    boolean changed;
+                    changed = conn.update(dc);
+                    hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
+                }
             }
 
             if (REPEAT_POLLING) {
@@ -1028,6 +1034,34 @@
             mIsInEmergencyCall = true;
         }
     }
+    /**
+     * Check the MT call to see if it's a new ring or
+     * a unknown connection.
+     */
+    private Connection checkMtFindNewRinging(DriverCall dc, int i) {
+
+        Connection newRinging = null;
+
+        connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
+        // it's a ringing call
+        if (connections[i].getCall() == ringingCall) {
+            newRinging = connections[i];
+            if (Phone.DEBUG_PHONE) log("Notify new ring " + dc);
+        } else {
+            // Something strange happened: a call which is neither
+            // a ringing call nor the one we created. It could be the
+            // call collision result from RIL
+            Log.e(LOG_TAG,"Phantom call appeared " + dc);
+            // If it's a connected call, set the connect time so that
+            // it's non-zero.  It may not be accurate, but at least
+            // it won't appear as a Missed Call.
+            if (dc.state != DriverCall.State.ALERTING
+                && dc.state != DriverCall.State.DIALING) {
+                connections[i].connectTime = System.currentTimeMillis();
+            }
+        }
+        return newRinging;
+    }
 
     /**
      * Check if current call is in emergency call
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 623d985..386dc3d46 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -299,14 +299,16 @@
 
         // Build up the data stream
         ByteArrayOutputStream output = new ByteArrayOutputStream();
-        for (int i = 0; i < totalSegments-1; i++) {
+        for (int i = 0; i < totalSegments; i++) {
             // reassemble the (WSP-)pdu
-            output.write(pdus[i], 0, pdus[i].length);
+            if (i == segment) {
+                // This one isn't in the DB, so add it
+                output.write(pdu, index, pdu.length - index);
+            } else {
+                output.write(pdus[i], 0, pdus[i].length);
+            }
         }
 
-        // This one isn't in the DB, so add it
-        output.write(pdu, index, pdu.length - index);
-
         byte[] datagram = output.toByteArray();
         // Dispatch the PDU to applications
         switch (destinationPort) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 165d583..266d127 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -69,7 +69,7 @@
  */
 public class SmsMessage extends SmsMessageBase {
     static final String LOG_TAG = "CDMA";
-    private final static Boolean DBG_SMS = false;
+    static private final String LOGGABLE_TAG = "CDMA:SMS";
 
     /**
      *  Status of a previously submitted SMS.
@@ -533,7 +533,7 @@
             return;
         }
         mBearerData = BearerData.decode(mEnvelope.bearerData);
-        if (DBG_SMS) {
+        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
             Log.d(LOG_TAG, "MT raw BearerData = '" +
                       HexDump.toHexString(mEnvelope.bearerData) + "'");
             Log.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
@@ -614,7 +614,7 @@
         int msgId = SystemProperties.getInt(TelephonyProperties.PROPERTY_CDMA_MSG_ID, 1);
         String nextMsgId = Integer.toString((msgId % 0xFFFF) + 1);
         SystemProperties.set(TelephonyProperties.PROPERTY_CDMA_MSG_ID, nextMsgId);
-        if (DBG_SMS) {
+        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
             Log.d(LOG_TAG, "next " + TelephonyProperties.PROPERTY_CDMA_MSG_ID + " = " + nextMsgId);
             Log.d(LOG_TAG, "readback gets " +
                     SystemProperties.get(TelephonyProperties.PROPERTY_CDMA_MSG_ID));
@@ -655,7 +655,7 @@
         bearerData.userData = userData;
 
         byte[] encodedBearerData = BearerData.encode(bearerData);
-        if (DBG_SMS) {
+        if (Log.isLoggable(LOGGABLE_TAG, Log.VERBOSE)) {
             Log.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
             Log.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
         }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
index a504cd3..a9be5bd 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/FileObserverTest.java
@@ -33,7 +33,7 @@
 public class FileObserverTest extends AndroidTestCase {
     private Observer mObserver;
     private File mTestFile;
-    
+
     private static class Observer extends FileObserver {
         public List<Map> events = Lists.newArrayList();
         public int totalEvents = 0;
@@ -56,10 +56,10 @@
             }
         }
     }
-    
+
     @Override
     protected void setUp() throws Exception {
-        mTestFile = File.createTempFile(".file_observer_test", ".txt"); 
+        mTestFile = File.createTempFile(".file_observer_test", ".txt");
     }
 
     @Override
@@ -68,13 +68,13 @@
             mTestFile.delete();
         }
     }
-    
+
     @LargeTest
     public void testRun() throws Exception {
         // make file changes and wait for them
         assertTrue(mTestFile.exists());
         assertNotNull(mTestFile.getParent());
-        
+
         mObserver = new Observer(mTestFile.getParent());
         mObserver.startWatching();
 
@@ -85,10 +85,11 @@
             waitForEvent(); // modify
 
             mTestFile.delete();
+            waitForEvent(); // modify
             waitForEvent(); // delete
 
             mObserver.stopWatching();
-            
+
             // Ensure that we have seen at least 3 events.
             assertTrue(mObserver.totalEvents > 3);
         } finally {
@@ -111,10 +112,41 @@
 
             while (it.hasNext()) {
                 Map map = it.next();
-                Log.i("FileObserverTest", "event: " + map.get("event").toString() + " path: " + map.get("path"));
+                Log.i("FileObserverTest", "event: " + getEventString((Integer)map.get("event")) + " path: " + map.get("path"));
             }
 
             mObserver.events.clear();
         }
     }
+
+    private String getEventString(int event) {
+        switch (event) {
+            case  FileObserver.ACCESS:
+                return "ACCESS";
+            case FileObserver.MODIFY:
+                return "MODIFY";
+            case FileObserver.ATTRIB:
+                return "ATTRIB";
+            case FileObserver.CLOSE_WRITE:
+                return "CLOSE_WRITE";
+            case FileObserver.CLOSE_NOWRITE:
+                return "CLOSE_NOWRITE";
+            case FileObserver.OPEN:
+                return "OPEN";
+            case FileObserver.MOVED_FROM:
+                return "MOVED_FROM";
+            case FileObserver.MOVED_TO:
+                return "MOVED_TO";
+            case FileObserver.CREATE:
+                return "CREATE";
+            case FileObserver.DELETE:
+                return "DELETE";
+            case FileObserver.DELETE_SELF:
+                return "DELETE_SELF";
+            case FileObserver.MOVE_SELF:
+                return "MOVE_SELF";
+            default:
+                return "UNKNOWN";
+        }
+    }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
index bd5c955..2f1a7389 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/PowerManagerTest.java
@@ -63,6 +63,8 @@
         wl = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK");
         doTestWakeLock(wl);
         
+        doTestSetBacklightBrightness();
+
         // TODO: Some sort of functional test (maybe not in the unit test here?) 
         // that confirms that things are really happening e.g. screen power, keyboard power.
 }
@@ -121,5 +123,20 @@
         // TODO: Threaded test (needs handler) to make sure timed wakelocks work too
     }
     
-    
+ 
+    /**
+     * Test that calling {@link android.os.IHardwareService#setBacklights(int)} requires
+     * permissions.
+     * <p>Tests permission:
+     *   {@link android.Manifest.permission#DEVICE_POWER}
+     */
+    private void doTestSetBacklightBrightness() {
+        try {
+            mPm.setBacklightBrightness(0);
+            fail("setBacklights did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
 }
diff --git a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
index 1263204..706c27e 100644
--- a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
+++ b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
@@ -36,27 +36,18 @@
 extern ANPCanvasInterfaceV0    gCanvasI;
 extern ANPLogInterfaceV0       gLogI;
 extern ANPPaintInterfaceV0     gPaintI;
-extern ANPSurfaceInterfaceV0   gSurfaceI;
 extern ANPTypefaceInterfaceV0  gTypefaceI;
 
 ///////////////////////////////////////////////////////////////////////////////
 
-EventPlugin::EventPlugin(NPP inst) : SubPlugin(inst) {
+EventPlugin::EventPlugin(NPP inst) : SubPlugin(inst) { }
 
-    // initialize the drawing surface
-    m_surfaceReady = false;
-    m_surface = gSurfaceI.newRasterSurface(inst, kRGB_565_ANPBitmapFormat, false);
-    if(!m_surface)
-        gLogI.log(inst, kError_ANPLogType, "----%p Unable to create Raster surface", inst);
-}
+EventPlugin::~EventPlugin() { }
 
-EventPlugin::~EventPlugin() {
-    gSurfaceI.deleteSurface(m_surface);
-}
+void EventPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {
 
-void EventPlugin::drawPlugin(int surfaceWidth, int surfaceHeight) {
-
-    gLogI.log(inst(), kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)", inst(), surfaceWidth, surfaceHeight);
+    gLogI.log(inst(), kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)",
+              inst(), bitmap.width, bitmap.height);
 
     // get the plugin's dimensions according to the DOM
     PluginObject *obj = (PluginObject*) inst()->pdata;
@@ -64,8 +55,8 @@
     const int H = obj->window->height;
 
     // compute the current zoom level
-    const float zoomFactorW = static_cast<float>(surfaceWidth) / W;
-    const float zoomFactorH = static_cast<float>(surfaceHeight) / H;
+    const float zoomFactorW = static_cast<float>(bitmap.width) / W;
+    const float zoomFactorH = static_cast<float>(bitmap.height) / H;
 
     // check to make sure the zoom level is uniform
     if (zoomFactorW + .01 < zoomFactorH && zoomFactorW - .01 > zoomFactorH)
@@ -76,15 +67,16 @@
     const int fontSize = (int)(zoomFactorW * 16);
     const int leftMargin = (int)(zoomFactorW * 10);
 
-    // lock the surface
-    ANPBitmap bitmap;
-    if (!m_surfaceReady || !gSurfaceI.lock(m_surface, &bitmap, NULL)) {
-        gLogI.log(inst(), kError_ANPLogType, " ------ %p unable to lock the plugin", inst());
-        return;
-    }
-
-    // create a canvas
+    // create and clip a canvas
     ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
+
+    ANPRectF clipR;
+    clipR.left = clip.left;
+    clipR.top = clip.top;
+    clipR.right = clip.right;
+    clipR.bottom = clip.bottom;
+    gCanvasI.clipRect(canvas, &clipR);
+
     gCanvasI.drawColor(canvas, 0xFFFFFFFF);
 
     // configure the paint
@@ -106,10 +98,9 @@
     const char c[] = "Browser Test Plugin";
     gCanvasI.drawText(canvas, c, sizeof(c)-1, leftMargin, -fm.fTop, paint);
 
-    // clean up variables and unlock the surface
+    // clean up variables
     gPaintI.deletePaint(paint);
     gCanvasI.deleteCanvas(canvas);
-    gSurfaceI.unlock(m_surface);
 }
 
 void EventPlugin::printToDiv(const char* text, int length) {
@@ -149,23 +140,16 @@
 
 int16 EventPlugin::handleEvent(const ANPEvent* evt) {
     switch (evt->eventType) {
-        case kDraw_ANPEventType:
-            gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request draw events", inst());
-            break;
-        case kSurface_ANPEventType:
-            switch (evt->data.surface.action) {
-                case kCreated_ANPSurfaceAction:
-                    m_surfaceReady = true;
+
+        case kDraw_ANPEventType: {
+            switch (evt->data.draw.model) {
+                case kBitmap_ANPDrawingModel:
+                    drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);
                     return 1;
-                case kDestroyed_ANPSurfaceAction:
-                    m_surfaceReady = false;
-                    return 1;
-                case kChanged_ANPSurfaceAction:
-                    drawPlugin(evt->data.surface.data.changed.width,
-                               evt->data.surface.data.changed.height);
-                    return 1;
+                default:
+                    break;   // unknown drawing model
             }
-            break;
+        }
         case kLifecycle_ANPEventType:
             switch (evt->data.lifecycle.action) {
                 case kOnLoad_ANPLifecycleAction: {
diff --git a/tests/BrowserTestPlugin/jni/event/EventPlugin.h b/tests/BrowserTestPlugin/jni/event/EventPlugin.h
index 73dd6ea..88b7c9d 100644
--- a/tests/BrowserTestPlugin/jni/event/EventPlugin.h
+++ b/tests/BrowserTestPlugin/jni/event/EventPlugin.h
@@ -35,11 +35,8 @@
     virtual int16 handleEvent(const ANPEvent* evt);
 
 private:
-    void drawPlugin(int surfaceWidth, int surfaceHeight);
+    void drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip);
     void printToDiv(const char* text, int length);
-
-    bool        m_surfaceReady;
-    ANPSurface* m_surface;
 };
 
 #endif // eventPlugin__DEFINED
diff --git a/tests/BrowserTestPlugin/jni/main.cpp b/tests/BrowserTestPlugin/jni/main.cpp
index 056ec4d..e3ad4a7 100644
--- a/tests/BrowserTestPlugin/jni/main.cpp
+++ b/tests/BrowserTestPlugin/jni/main.cpp
@@ -65,7 +65,6 @@
 ANPLogInterfaceV0           gLogI;
 ANPPaintInterfaceV0         gPaintI;
 ANPPathInterfaceV0          gPathI;
-ANPSurfaceInterfaceV0       gSurfaceI;
 ANPSystemInterfaceV0        gSystemI;
 ANPTypefaceInterfaceV0      gTypefaceI;
 ANPWindowInterfaceV0        gWindowI;
@@ -105,16 +104,10 @@
         uint32_t        size;
         ANPInterface*   i;
     } gPairs[] = {
-        { kAudioTrackInterfaceV0_ANPGetValue,   sizeof(gSoundI),    &gSoundI },
-        { kBitmapInterfaceV0_ANPGetValue,       sizeof(gBitmapI),   &gBitmapI },
         { kCanvasInterfaceV0_ANPGetValue,       sizeof(gCanvasI),   &gCanvasI },
         { kLogInterfaceV0_ANPGetValue,          sizeof(gLogI),      &gLogI },
         { kPaintInterfaceV0_ANPGetValue,        sizeof(gPaintI),    &gPaintI },
-        { kPathInterfaceV0_ANPGetValue,         sizeof(gPathI),     &gPathI },
-        { kSurfaceInterfaceV0_ANPGetValue,      sizeof(gSurfaceI),  &gSurfaceI },
-        { kSystemInterfaceV0_ANPGetValue,       sizeof(gSystemI),   &gSystemI },
         { kTypefaceInterfaceV0_ANPGetValue,     sizeof(gTypefaceI), &gTypefaceI },
-        { kWindowInterfaceV0_ANPGetValue,       sizeof(gWindowI),   &gWindowI },
     };
     for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) {
         gPairs[i].i->inSize = gPairs[i].size;
@@ -156,7 +149,7 @@
     }
 
     // select the drawing model
-    ANPDrawingModel model = kSurface_ANPDrawingModel;
+    ANPDrawingModel model = kBitmap_ANPDrawingModel;
 
     // notify the plugin API of the drawing model we wish to use. This must be
     // done prior to creating certain subPlugin objects (e.g. surfaceViews)
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 4a68d72..7dd4a88 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -88,8 +88,15 @@
 
   result_file = "/sdcard/load_test_result.txt"
   shell_cmd_str = adb_cmd + " pull " + result_file + " " + results_dir
-  adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
-  logging.info(adb_output)
+  (adb_output, err) = subprocess.Popen(
+      shell_cmd_str, shell=True,
+      stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+  if not os.path.isfile(os.path.join(results_dir, "load_test_result.txt")):
+    logging.error("Failed to pull result file.")
+    logging.error("adb stdout:")
+    logging.error(adb_output)
+    logging.error("adb stderr:")
+    logging.error(err)
   logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n")
 
 if '__main__' == __name__:
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
index 5644044..6d5996c 100644
--- a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
+++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
@@ -16,7 +16,7 @@
 
 package com.android.frameworktest.settings;
 
-import android.os.IHardwareService;
+import android.os.IPowerManager;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -45,11 +45,11 @@
     }
 
     public void onClick(View v) {
-        IHardwareService hardware = IHardwareService.Stub.asInterface(
-                ServiceManager.getService("hardware"));
-        if (hardware != null) {
+        IPowerManager power = IPowerManager.Stub.asInterface(
+                ServiceManager.getService("power"));
+        if (power != null) {
             try {
-                hardware.setBacklights(0);
+                power.setBacklightBrightness(0);
             } catch (RemoteException darn) {
                 
             }
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
index 1ba9d66a..dc959f5 100644
--- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -188,9 +188,9 @@
         previousResults[3] = new ContentProviderResult(103);
 
         ContentValues expectedValues = new ContentValues(values);
-        expectedValues.put("a1", "103");
-        expectedValues.put("a2", "101");
-        expectedValues.put("a3", "102");
+        expectedValues.put("a1", (long) 103);
+        expectedValues.put("a2", (long) 101);
+        expectedValues.put("a3", (long) 102);
 
         ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
                 .withValues(values)
diff --git a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
index aebd68c..2290c1d 100644
--- a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
@@ -117,20 +117,4 @@
             // expected
         }
     }
-
-    /**
-     * Test that calling {@link android.os.IHardwareService#setBacklights(int)} requires
-     * permissions.
-     * <p>Tests permission:
-     *   {@link android.Manifest.permission#HARDWARE_TEST}
-     * @throws RemoteException
-     */
-    public void testSetBacklights() throws RemoteException {
-        try {
-            mHardwareService.setBacklights(0);
-            fail("setBacklights did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
 }