auto import from //branches/cupcake_rel/...@138607
diff --git a/api/current.xml b/api/current.xml
index 858b1e9..f45b68f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -11018,6 +11018,56 @@
 >
 </field>
 </class>
+<class name="R.integer"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.integer"
+ type="android.R.integer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="config_longAnimTime"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694722"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="config_mediumAnimTime"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694721"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="config_shortAnimTime"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17694720"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.layout"
  extends="java.lang.Object"
  abstract="false"
@@ -28374,6 +28424,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_SEARCH_LONG_PRESS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.SEARCH_LONG_PRESS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_SEND"
  type="java.lang.String"
  transient="false"
@@ -66360,6 +66421,21 @@
 <parameter name="c" type="android.hardware.Camera">
 </parameter>
 </method>
+<method name="setMaxDuration"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="max_duration_ms" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
 <method name="setOnErrorListener"
  return="void"
  abstract="false"
@@ -66373,6 +66449,19 @@
 <parameter name="l" type="android.media.MediaRecorder.OnErrorListener">
 </parameter>
 </method>
+<method name="setOnInfoListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.MediaRecorder.OnInfoListener">
+</parameter>
+</method>
 <method name="setOutputFile"
  return="void"
  abstract="false"
@@ -66530,6 +66619,28 @@
  visibility="public"
 >
 </field>
+<field name="MEDIA_RECORDER_INFO_MAX_DURATION_REACHED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="800"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_RECORDER_INFO_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="MediaRecorder.AudioEncoder"
  extends="java.lang.Object"
@@ -66618,6 +66729,31 @@
 </parameter>
 </method>
 </interface>
+<interface name="MediaRecorder.OnInfoListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onInfo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mr" type="android.media.MediaRecorder">
+</parameter>
+<parameter name="what" type="int">
+</parameter>
+<parameter name="extra" type="int">
+</parameter>
+</method>
+</interface>
 <class name="MediaRecorder.OutputFormat"
  extends="java.lang.Object"
  abstract="false"
@@ -84442,6 +84578,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_APPLICATION_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;com.android.browser.application_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="HISTORY_PROJECTION"
  type="java.lang.String[]"
  transient="false"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 5ef7499..eabf98e 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -130,7 +130,7 @@
         /* the full dumpsys is starting to take a long time, so we need
            to increase its timeout.  we really need to do the timeouts in
            dumpsys itself... */
-        EXEC_TIMEOUT("dumpsys", 40);
+        EXEC_TIMEOUT("dumpsys", 60);
     }
 }
 
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 33127fb..6862e5a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -19,8 +19,8 @@
 
 #include <time.h>
 
-// Commands time out after 15 seconds
-#define TIMEOUT     15
+// Commands time out after 60 seconds
+#define TIMEOUT     60
 
 #define PRINT(s) printf("%s\n", s)
 
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 15e0a4d..64288d2e 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -126,14 +126,6 @@
 
     // support for AutoCompleteTextView suggestions display
     private SuggestionsAdapter mSuggestionsAdapter;
-    private Handler mHandler = new Handler();
-    private Runnable mInstallSuggestionAdapter = new Runnable() {
-        public void run() {
-            if (mSearchTextField != null) {
-                mSearchTextField.setAdapter(mSuggestionsAdapter);
-            }
-        }
-    };
 
     /**
      * Constructor - fires it up and makes it look like the search UI.
@@ -261,8 +253,8 @@
             mSearchTextField.setAdapter(mSuggestionsAdapter);
             mSearchTextField.setText(initialQuery);
         } else {
-            mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable,
-                    mHandler, mInstallSuggestionAdapter);
+            mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, 
+                    mSearchTextField);
             mSearchTextField.setAdapter(mSuggestionsAdapter);
 
             // finally, load the user's initial text (which may trigger suggestions)
@@ -1305,15 +1297,13 @@
         // These private variables are shared by the filter thread and must be protected
         private WeakReference<Cursor> mRecentCursor = new WeakReference<Cursor>(null);
         private boolean mNonUserQuery = false;
-        private Handler mHandler;
-        private Runnable mInstallSuggestionAdapter;
+        private AutoCompleteTextView mParentView;
 
         public SuggestionsAdapter(Context context, SearchableInfo searchable,
-                Handler handler, Runnable installSuggestionAdapter) {
+                AutoCompleteTextView actv) {
             super(context, -1, null, null, null);
             mSearchable = searchable;
-            mHandler = handler;
-            mInstallSuggestionAdapter = installSuggestionAdapter;
+            mParentView = actv;
             
             // set up provider resources (gives us icons, etc.)
             Context activityContext = mSearchable.getActivityContext(mContext);
@@ -1426,13 +1416,12 @@
                         to = ONE_LINE_TO;
                     }
                 }
+                // Force the underlying ListView to discard and reload all layouts
+                // (Note, this should be optimized for cases where layout/cursor remain same)
+                mParentView.resetListAndClearViews();
                 // Now actually set up the cursor, columns, and the list view
                 changeCursorAndColumns(c, from, to);
                 setViewResource(layout);          
-                // Force the underlying ListView to discard and reload all layouts
-                // (Note, this could be optimized for cases where layout/cursor remain same)
-                mHandler.post(mInstallSuggestionAdapter);
-
             } else {
                 // Provide some help for developers instead of just silently discarding
                 Log.w(LOG_TAG, "Suggestions cursor discarded due to missing required columns.");
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index e23545b..1dbe0cc 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -67,6 +67,11 @@
     /** A headset is currently connected */
     public static final int STATE_CONNECTED    = 2;
 
+    /** A SCO audio channel is not established */
+    public static final int AUDIO_STATE_DISCONNECTED = 0;
+    /** A SCO audio channel is established */
+    public static final int AUDIO_STATE_CONNECTED = 1;
+
     public static final int RESULT_FAILURE = 0;
     public static final int RESULT_SUCCESS = 1;
     /** Connection canceled before completetion. */
diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java
index b66b06e..9273d0d 100644
--- a/core/java/android/bluetooth/BluetoothIntent.java
+++ b/core/java/android/bluetooth/BluetoothIntent.java
@@ -45,6 +45,8 @@
         "android.bluetooth.intent.HEADSET_STATE";
     public static final String HEADSET_PREVIOUS_STATE =
         "android.bluetooth.intent.HEADSET_PREVIOUS_STATE";
+    public static final String HEADSET_AUDIO_STATE =
+        "android.bluetooth.intent.HEADSET_AUDIO_STATE";
     public static final String BOND_STATE =
         "android.bluetooth.intent.BOND_STATE";
     public static final String BOND_PREVIOUS_STATE =
@@ -122,7 +124,18 @@
     public static final String BOND_STATE_CHANGED_ACTION      =
         "android.bluetooth.intent.action.BOND_STATE_CHANGED_ACTION";
 
+    /**
+     * TODO(API release): Move into BluetoothHeadset
+     */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String HEADSET_STATE_CHANGED_ACTION      =
         "android.bluetooth.intent.action.HEADSET_STATE_CHANGED";
+
+    /**
+     * TODO(API release): Consider incorporating as new state in
+     * HEADSET_STATE_CHANGED
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String HEADSET_AUDIO_STATE_CHANGED_ACTION =
+        "android.bluetooth.intent.action.HEADSET_ADUIO_STATE_CHANGED";
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index bb80e10..90ff78a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1026,6 +1026,15 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
+
+    /**
+     * Activity Action: Start action associated with long pressing on the
+     * search key.
+     * <p>Input: Nothing.
+     * <p>Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
     
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index f58b7ef..7a63c0c 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -16,34 +16,33 @@
 
 package android.inputmethodservice;
 
-import com.android.internal.R;
-
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.graphics.Paint.Align;
+import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.Keyboard.Key;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Vibrator;
-import android.preference.PreferenceManager;
+import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewGroup.LayoutParams;
-import android.widget.Button;
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
+import com.android.internal.R;
+
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -221,6 +220,15 @@
     private static final int MULTITAP_INTERVAL = 800; // milliseconds
     private StringBuilder mPreviewLabel = new StringBuilder(1);
 
+    /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/
+    private boolean mDrawPending;
+    /** The dirty region in the keyboard bitmap */
+    private Rect mDirtyRect = new Rect();
+    /** The keyboard bitmap for faster updates */
+    private Bitmap mBuffer;
+    /** The canvas for the above mutable keyboard bitmap */
+    private Canvas mCanvas;
+    
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -396,7 +404,10 @@
         List<Key> keys = mKeyboard.getKeys();
         mKeys = keys.toArray(new Key[keys.size()]);
         requestLayout();
-        invalidate();
+        // Release buffer, just in case the new keyboard has a different size. 
+        // It will be reallocated on the next draw.
+        mBuffer = null;
+        invalidateAll();
         computeProximityThreshold(keyboard);
         mMiniKeyboardCache.clear(); // Not really necessary to do every time, but will free up views
     }
@@ -420,7 +431,7 @@
         if (mKeyboard != null) {
             if (mKeyboard.setShifted(shifted)) {
                 // The whole keyboard probably needs to be redrawn
-                invalidate();
+                invalidateAll();
                 return true;
             }
         }
@@ -545,8 +556,30 @@
     }
 
     @Override
+    public void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        // Release the buffer, if any and it will be reallocated on the next draw
+        mBuffer = null;
+    }
+
+    @Override
     public void onDraw(Canvas canvas) {
         super.onDraw(canvas);
+        if (mDrawPending || mBuffer == null) {
+            onBufferDraw();
+        }
+        canvas.drawBitmap(mBuffer, 0, 0, null);
+    }
+    
+    private void onBufferDraw() {
+        if (mBuffer == null) {
+            mBuffer = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
+            mCanvas = new Canvas(mBuffer);
+            invalidateAll();
+        }
+        final Canvas canvas = mCanvas;
+        canvas.clipRect(mDirtyRect, Op.REPLACE);
+        
         if (mKeyboard == null) return;
         
         final Paint paint = mPaint;
@@ -557,24 +590,20 @@
         final int kbdPaddingTop = mPaddingTop;
         final Key[] keys = mKeys;
         final Key invalidKey = mInvalidatedKey;
-        //canvas.translate(0, mKeyboardPaddingTop);
+
         paint.setAlpha(255);
         paint.setColor(mKeyTextColor);
         boolean drawSingleKey = false;
         if (invalidKey != null && canvas.getClipBounds(clipRegion)) {
-//            System.out.println("Key bounds = " + (invalidKey.x + mPaddingLeft) + ","
-//                    + (invalidKey.y + mPaddingTop) + "," 
-//                    + (invalidKey.x + invalidKey.width + mPaddingLeft) + "," 
-//                    + (invalidKey.y + invalidKey.height + mPaddingTop));
-//            System.out.println("Clip bounds =" + clipRegion.toShortString());
-            // Is clipRegion completely contained within the invalidated key?
-            if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left &&
-                    invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top &&
-                    invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right &&
-                    invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) {
-                drawSingleKey = true;
-            }
+          // Is clipRegion completely contained within the invalidated key?
+          if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left &&
+                  invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top &&
+                  invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right &&
+                  invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) {
+              drawSingleKey = true;
+          }
         }
+        canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
         final int keyCount = keys.length;
         for (int i = 0; i < keyCount; i++) {
             final Key key = keys[i];
@@ -645,6 +674,9 @@
             paint.setColor(0xFF00FF00);
             canvas.drawCircle((mStartX + mLastX) / 2, (mStartY + mLastY) / 2, 2, paint);
         }
+        
+        mDrawPending = false;
+        mDirtyRect.setEmpty();
     }
 
     private int getKeyIndices(int x, int y, int[] allKeys) {
@@ -844,12 +876,21 @@
         mPreviewText.setVisibility(VISIBLE);
     }
 
+    private void invalidateAll() {
+        mDirtyRect.union(0, 0, getWidth(), getHeight());
+        mDrawPending = true;
+        invalidate();
+    }
+    
     private void invalidateKey(int keyIndex) {
         if (keyIndex < 0 || keyIndex >= mKeys.length) {
             return;
         }
         final Key key = mKeys[keyIndex];
         mInvalidatedKey = key;
+        mDirtyRect.union(key.x + mPaddingLeft, key.y + mPaddingTop, 
+                key.x + key.width + mPaddingLeft, key.y + key.height + mPaddingTop);
+        onBufferDraw();
         invalidate(key.x + mPaddingLeft, key.y + mPaddingTop, 
                 key.x + key.width + mPaddingLeft, key.y + key.height + mPaddingTop);
     }
@@ -952,7 +993,7 @@
             mPopupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
             mMiniKeyboardOnScreen = true;
             //mMiniKeyboard.onTouchEvent(getTranslatedEvent(me));
-            invalidate();
+            invalidateAll();
             return true;
         }
         return false;
@@ -1066,11 +1107,11 @@
                 }
                 showPreview(NOT_A_KEY);
                 Arrays.fill(mKeyIndices, NOT_A_KEY);
-                invalidateKey(keyIndex);
                 // If we're not on a repeating key (which sends on a DOWN event)
                 if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) {
                     detectAndSendKey(touchX, touchY, eventTime);
                 }
+                invalidateKey(keyIndex);
                 mRepeatKeyIndex = NOT_A_KEY;
                 break;
         }
@@ -1110,7 +1151,8 @@
         mHandler.removeMessages(MSG_SHOW_PREVIEW);
         
         dismissPopupKeyboard();
-        
+        mBuffer = null;
+        mCanvas = null;
         mMiniKeyboardCache.clear();
     }
     
@@ -1124,10 +1166,10 @@
         if (mPopupKeyboard.isShowing()) {
             mPopupKeyboard.dismiss();
             mMiniKeyboardOnScreen = false;
-            invalidate();
+            invalidateAll();
         }
     }
-    
+
     public boolean handleBack() {
         if (mPopupKeyboard.isShowing()) {
             dismissPopupKeyboard();
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl
index 88dae85..96d44b6 100644
--- a/core/java/android/os/IMountService.aidl
+++ b/core/java/android/os/IMountService.aidl
@@ -50,7 +50,7 @@
     void unmountMedia(String mountPoint);
 
     /**
-     * Format external storage given a mount point
+     * Format external storage given a mount point.
      */
     void formatMedia(String mountPoint);
 
@@ -63,4 +63,16 @@
      * Sets whether or not media notification sounds are played.
      */
     void setPlayNotificationSounds(boolean value);
+
+    /**
+     * Returns true if USB Mass Storage is automatically started
+     * when a UMS host is detected.
+     */
+    boolean getAutoStartUms();
+
+    /**
+     * Sets whether or not USB Mass Storage is automatically started
+     * when a UMS host is detected.
+     */
+    void setAutoStartUms(boolean value);
 }
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index 6e215dc..20702a1 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -194,13 +194,6 @@
         }
         
         private void sample() {
-    
-            // Only play a preview sample when controlling the ringer stream
-            if (mStreamType != AudioManager.STREAM_RING
-                    && mStreamType != AudioManager.STREAM_NOTIFICATION) {
-                return;
-            }
-    
             onSampleStarting(this);
             mRingtone.play();
         }
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 76aa51d..c597b3c 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -43,6 +43,18 @@
      */
     public static final String INITIAL_ZOOM_LEVEL = "browser.initialZoomLevel";
 
+    /**
+     * The name of the extra data when starting the Browser from another
+     * application.
+     * <p>
+     * The value is a unique identification string that will be used to
+     * indentify the calling application. The Browser will attempt to reuse the
+     * same window each time the application launches the Browser with the same
+     * identifier.
+     */
+    public static final String EXTRA_APPLICATION_ID =
+            "com.android.browser.application_id";
+
     /* if you change column order you must also change indices
        below */
     public static final String[] HISTORY_PROJECTION = new String[] {
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index d0bd2a5..2aa77ea 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -182,7 +182,7 @@
          * <p>Type: TEXT</P>
          */
         public static final String PHONETIC_NAME = "phonetic_name";
-
+        
         /**
          * The display name. If name is not null name, else if number is not null number,
          * else if email is not null email.
@@ -191,6 +191,14 @@
         public static final String DISPLAY_NAME = "display_name";
 
         /**
+         * The field for sorting list phonetically. The content of this field
+         * may not be human readable but phonetically sortable.
+         * <P>Type: TEXT</p>
+         * @hide Used only in Contacts application for now.
+         */
+        public static final String SORT_STRING = "sort_string";
+        
+        /**
          * Notes about the person.
          * <P>Type: TEXT</P>
          */
@@ -231,7 +239,7 @@
          * The server version of the photo
          * <P>Type: TEXT (the version number portion of the photo URI)</P>
          */
-        public static final String PHOTO_VERSION = "photo_version";
+        public static final String PHOTO_VERSION = "photo_version";       
     }
 
     /**
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index e271909..9e9ba62 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -81,10 +81,13 @@
      */
     public synchronized void init() {
         initializeNativeDataNative();
-        mIsEnabled = (isEnabledNative() == 1);
-        if (mIsEnabled) {
-            mBondState.loadBondState();
+
+        if (isEnabledNative() == 1) {
+            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
+            disableNative();
         }
+
+        mIsEnabled = false;
         mIsDiscovering = false;
         mEventLoop = new BluetoothEventLoop(mContext, this);
         registerForAirplaneMode();
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index efb88a0e..29c0c76 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -88,6 +88,7 @@
         super(verticalAlignment);
         mContext = context;
         mContentUri = uri;
+        mSource = uri.toString();
     }
 
     public ImageSpan(Context context, int resourceId) {
@@ -117,6 +118,8 @@
                         mContentUri);
                 bitmap = BitmapFactory.decodeStream(is);
                 drawable = new BitmapDrawable(bitmap);
+                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
+                        drawable.getIntrinsicHeight());
                 is.close();
             } catch (Exception e) {
                 Log.e("sms", "Failed to loaded content " + mContentUri, e);
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index f458611..d29bfb6 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -16,9 +16,11 @@
 
 package android.text.style;
 
+import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
+import android.provider.Browser;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
 import android.view.View;
@@ -54,8 +56,9 @@
     @Override
     public void onClick(View widget) {
         Uri uri = Uri.parse(getURL());
+        Context context = widget.getContext();
         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
-        intent.addCategory(Intent.CATEGORY_BROWSABLE);
-        widget.getContext().startActivity(intent);
+        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
+        context.startActivity(intent);
     }
 }
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
index 4c128ad..a349b82 100644
--- a/core/java/android/text/util/Regex.java
+++ b/core/java/android/text/util/Regex.java
@@ -66,9 +66,9 @@
     public static final Pattern WEB_URL_PATTERN
         = Pattern.compile(
             "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
-            + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
-            + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+)?\\@)?)?"
-            + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*\\.)+"   // named host
+            + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+            + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+            + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
             + "(?:"   // plus top level domain
             + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
             + "|(?:biz|b[abdefghijmnorstvwyz])"
@@ -122,12 +122,12 @@
 
     public static final Pattern EMAIL_ADDRESS_PATTERN
         = Pattern.compile(
-            "[a-zA-Z0-9\\+\\.\\_\\%\\-]+" +
+            "[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}" +
             "\\@" +
-            "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
+            "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
             "(" +
                 "\\." +
-                "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
+                "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
             ")+"
         );
 
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 0a043bd..6ea7a82 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -663,7 +663,7 @@
                     public Object[] pre() {
                         final DisplayMetrics metrics = view.getResources().getDisplayMetrics();
                         final Bitmap bitmap = Bitmap.createBitmap(metrics.widthPixels,
-                                metrics.heightPixels, Bitmap.Config.ARGB_8888);
+                                metrics.heightPixels, Bitmap.Config.RGB_565);
                         final Canvas canvas = new Canvas(bitmap);
                         return new Object[] { bitmap, canvas };
                     }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 9b13d38..dd2b154 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -219,7 +219,7 @@
         mVisRect = new Rect();
         mVisPoint = new Point();
         mWinFrame = new Rect();
-        mWindow = new W(this);
+        mWindow = new W(this, context);
         mInputMethodCallback = new InputMethodCallback(this);
         mViewVisibility = View.GONE;
         mTransparentRegion = new Region();
@@ -2453,11 +2453,71 @@
         }
     }
     
+    static class EventCompletion extends Handler {
+        final IWindow mWindow;
+        final KeyEvent mKeyEvent;
+        final boolean mIsPointer;
+        final MotionEvent mMotionEvent;
+        
+        EventCompletion(Looper looper, IWindow window, KeyEvent key,
+                boolean isPointer, MotionEvent motion) {
+            super(looper);
+            mWindow = window;
+            mKeyEvent = key;
+            mIsPointer = isPointer;
+            mMotionEvent = motion;
+            sendEmptyMessage(0);
+        }
+        
+        @Override
+        public void handleMessage(Message msg) {
+            if (mKeyEvent != null) {
+                try {
+                    sWindowSession.finishKey(mWindow);
+                 } catch (RemoteException e) {
+                 }
+            } else if (mIsPointer) {
+                boolean didFinish;
+                MotionEvent event = mMotionEvent;
+                if (event == null) {
+                    try {
+                        event = sWindowSession.getPendingPointerMove(mWindow);
+                    } catch (RemoteException e) {
+                    }
+                    didFinish = true;
+                } else {
+                    didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
+                }
+                if (!didFinish) {
+                    try {
+                        sWindowSession.finishKey(mWindow);
+                     } catch (RemoteException e) {
+                     }
+                }
+            } else {
+                MotionEvent event = mMotionEvent;
+                if (event == null) {
+                    try {
+                        event = sWindowSession.getPendingTrackballMove(mWindow);
+                    } catch (RemoteException e) {
+                    }
+                } else {
+                    try {
+                        sWindowSession.finishKey(mWindow);
+                     } catch (RemoteException e) {
+                     }
+                }
+            }
+        }
+    }
+    
     static class W extends IWindow.Stub {
-        private WeakReference<ViewRoot> mViewRoot;
+        private final WeakReference<ViewRoot> mViewRoot;
+        private final Looper mMainLooper;
 
-        public W(ViewRoot viewRoot) {
+        public W(ViewRoot viewRoot, Context context) {
             mViewRoot = new WeakReference<ViewRoot>(viewRoot);
+            mMainLooper = context.getMainLooper();
         }
 
         public void resized(int w, int h, Rect coveredInsets,
@@ -2475,6 +2535,7 @@
                 viewRoot.dispatchKey(event);
             } else {
                 Log.w("ViewRoot.W", "Key event " + event + " but no ViewRoot available!");
+                new EventCompletion(mMainLooper, this, event, false, null);
             }
         }
 
@@ -2482,6 +2543,8 @@
             final ViewRoot viewRoot = mViewRoot.get();
             if (viewRoot != null) {
                 viewRoot.dispatchPointer(event, eventTime);
+            } else {
+                new EventCompletion(mMainLooper, this, null, true, event);
             }
         }
 
@@ -2489,6 +2552,8 @@
             final ViewRoot viewRoot = mViewRoot.get();
             if (viewRoot != null) {
                 viewRoot.dispatchTrackball(event, eventTime);
+            } else {
+                new EventCompletion(mMainLooper, this, null, false, event);
             }
         }
 
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 5877932..f1f5f70 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -34,24 +34,12 @@
     private static final String TAG = "WindowOrientationListener";
     private static final boolean DEBUG = false;
     private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
-    private int mOrientation = ORIENTATION_UNKNOWN;
     private SensorManager mSensorManager;
     private boolean mEnabled = false;
     private int mRate;
     private Sensor mSensor;
     private SensorEventListener mSensorEventListener;
-    
-    /**
-     * Returned from onOrientationChanged when the device orientation cannot be determined
-     * (typically when the device is in a close to flat position).
-     *
-     *  @see #onOrientationChanged
-     */
-    public static final int ORIENTATION_UNKNOWN = -1;
-    /*
-     * Returned when the device is almost lying flat on a surface
-     */
-    public static final int ORIENTATION_FLAT = -2;
+    private int mSensorRotation = -1;
 
     /**
      * Creates a new WindowOrientationListener.
@@ -116,24 +104,47 @@
         private static final int _DATA_X = 0;
         private static final int _DATA_Y = 1;
         private static final int _DATA_Z = 2;
+        // Angle around x-axis thats considered almost perfect vertical to hold
+        // the device
+        private static final int PIVOT = 30;
+        // Angle around x-asis that's considered almost too vertical. Beyond
+        // this angle will not result in any orientation changes. f phone faces uses,
+        // the device is leaning backward.
+        private static final int PIVOT_UPPER = 65;
+        // Angle about x-axis that's considered negative vertical. Beyond this
+        // angle will not result in any orientation changes. If phone faces uses,
+        // the device is leaning forward.
+        private static final int PIVOT_LOWER = 0;
+        // Upper threshold limit for switching from portrait to landscape
+        private static final int PL_UPPER = 280;
+        // Lower threshold limit for switching from landscape to portrait
+        private static final int LP_LOWER = 320;
+        // Lower threshold limt for switching from portrait to landscape
+        private static final int PL_LOWER = 240;
+        // Upper threshold limit for switching from landscape to portrait
+        private static final int LP_UPPER = 360;
+        
+        // Internal value used for calculating linear variant
+        private static final float PL_LINEAR_FACTOR =
+            ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT_UPPER-PIVOT_LOWER));
+        //  Internal value used for calculating linear variant
+        private static final float LP_LINEAR_FACTOR =
+            ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT_UPPER-PIVOT_LOWER));
         
         public void onSensorChanged(SensorEvent event) {
             float[] values = event.values;
-            int orientation = ORIENTATION_UNKNOWN;
             float X = values[_DATA_X];
             float Y = values[_DATA_Y];
             float Z = values[_DATA_Z];
             float OneEightyOverPi = 57.29577957855f;
             float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
             float zyangle = Math.abs((float)Math.asin(Z/gravity)*OneEightyOverPi);
-            // The device is considered flat if the angle is more than 75
-            // if the angle is less than 40, its considered too flat to switch
-            // orientation. if the angle is between 40 - 75, the orientation is unknown
-            if (zyangle < 40) {
+            int rotation = mSensorRotation;
+            if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) {
                 // Check orientation only if the phone is flat enough
                 // Don't trust the angle if the magnitude is small compared to the y value
                 float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
-                orientation = 90 - (int)Math.round(angle);
+                int orientation = 90 - (int)Math.round(angle);
                 // normalize to 0 - 359 range
                 while (orientation >= 360) {
                     orientation -= 360;
@@ -141,13 +152,24 @@
                 while (orientation < 0) {
                     orientation += 360;
                 }
-            } else if (zyangle >= 75){
-                orientation = ORIENTATION_FLAT;
+               
+                float delta = (float)Math.abs(zyangle - PIVOT);
+                if (((orientation >= 0) && (orientation <= LP_UPPER)) ||
+                        (orientation >= PL_LOWER)) {
+                    float threshold;
+                    if (mSensorRotation == Surface.ROTATION_90) {
+                        threshold = LP_LOWER + (LP_LINEAR_FACTOR * delta) ;
+                    } else {
+                        threshold = PL_UPPER - (PL_LINEAR_FACTOR * delta);
+                    }
+                    rotation = (orientation >= PL_LOWER &&
+                            orientation <= threshold) ? Surface.ROTATION_90 : Surface.ROTATION_0;
+                }
+                
             }
-            
-            if (orientation != mOrientation) {
-                mOrientation = orientation;
-                onOrientationChanged(orientation);
+            if (rotation != mSensorRotation) {
+                mSensorRotation = rotation;
+                onOrientationChanged(mSensorRotation);
             }
         }
 
@@ -164,17 +186,11 @@
     }
     
     /**
-     * Called when the orientation of the device has changed.
-     * orientation parameter is in degrees, ranging from 0 to 359.
-     * orientation is 0 degrees when the device is oriented in its natural position,
-     * 90 degrees when its left side is at the top, 180 degrees when it is upside down, 
-     * and 270 degrees when its right side is to the top.
-     * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
-     * and the orientation cannot be determined.
-     *
-     * @param orientation The new orientation of the device.
+     * Called when the rotation view of the device has changed.
+     * Can be either Surface.ROTATION_90 or Surface.ROTATION_0.
+     * @param rotation The new orientation of the device.
      *
      *  @see #ORIENTATION_UNKNOWN
      */
-    abstract public void onOrientationChanged(int orientation);
+    abstract public void onOrientationChanged(int rotation);
 }
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index d12940d..dcf68cd 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -52,6 +52,7 @@
 
     private static final String NO_STORE = "no-store";
     private static final String NO_CACHE = "no-cache";
+    private static final String PRIVATE  = "private";
     private static final String MAX_AGE = "max-age";
 
     private static long CACHE_THRESHOLD = 6 * 1024 * 1024;
@@ -612,7 +613,7 @@
                 // must be re-validated on every load. It does not mean that
                 // the content can not be cached. set to expire 0 means it
                 // can only be used in CACHE_MODE_CACHE_ONLY case
-                if (NO_CACHE.equals(controls[i])) {
+                if (NO_CACHE.equals(controls[i]) || PRIVATE.equals(controls[i])) {
                     ret.expires = 0;
                 } else if (controls[i].startsWith(MAX_AGE)) {
                     int separator = controls[i].indexOf('=');
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 84aeb83..0f9f29c 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -29,6 +29,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
+import android.provider.Browser;
 import android.util.Config;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -175,6 +176,11 @@
             Intent intent = new Intent(Intent.ACTION_VIEW,
                     Uri.parse(overrideUrl));
             intent.addCategory(Intent.CATEGORY_BROWSABLE);
+            // If another application is running a WebView and launches the
+            // Browser through this Intent, we want to reuse the same window if
+            // possible.
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID,
+                    mContext.getPackageName());
             try {
                 mContext.startActivity(intent);
                 override = true;
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 07c1a5d..d90a2fd 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -743,11 +743,16 @@
              * Note: in the case of "foo=bluh, bar=bluh;path=/", we interpret
              * it as one cookie instead of two cookies.
              */
+            int semicolonIndex = cookieString.indexOf(SEMICOLON, index);
             int equalIndex = cookieString.indexOf(EQUAL, index);
             if (equalIndex == -1) {
                 // bad format, force return
                 break;
             }
+            if (semicolonIndex > -1 && semicolonIndex < equalIndex) {
+                // empty cookie, like "; path=/", return
+                break;
+            }
             cookie = new Cookie(host, path);
             cookie.name = cookieString.substring(index, equalIndex);
             if (cookieString.charAt(equalIndex + 1) == QUOTATION) {
@@ -757,7 +762,7 @@
                     break;
                 }
             }
-            int semicolonIndex = cookieString.indexOf(SEMICOLON, index);
+            semicolonIndex = cookieString.indexOf(SEMICOLON, index);
             if (semicolonIndex == -1) {
                 semicolonIndex = length;
             }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f61ce40..753267f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -180,9 +180,6 @@
      */
     VelocityTracker mVelocityTracker;
 
-    private static boolean mShowZoomTutorial = true;
-    private static final int ZOOM_TUTORIAL_DURATION = 3000;
-
     /**
      * Touch mode
      */
@@ -223,16 +220,12 @@
      */
     // pre-computed square of ViewConfiguration.getScaledTouchSlop()
     private int mTouchSlopSquare;
-    // pre-computed square of the density adjusted double tap slop
-    private int mDoubleTapSlopSquare;
     // pre-computed density adjusted navigation slop
     private int mNavSlop;
     // This should be ViewConfiguration.getTapTimeout()
     // But system time out is 100ms, which is too short for the browser.
     // In the browser, if it switches out of tap too soon, jump tap won't work.
     private static final int TAP_TIMEOUT = 200;
-    // The duration in milliseconds we will wait to see if it is a double tap.
-    private static final int DOUBLE_TAP_TIMEOUT = 250;
     // This should be ViewConfiguration.getLongPressTimeout()
     // But system time out is 500ms, which is too short for the browser.
     // With a short timeout, it's difficult to treat trigger a short press.
@@ -258,11 +251,6 @@
     private int mContentWidth;   // cache of value from WebViewCore
     private int mContentHeight;  // cache of value from WebViewCore
 
-    static int MAX_FLOAT_CONTENT_WIDTH = 480;
-    // the calculated minimum content width for calculating the minimum scale.
-    // If it is 0, it means don't use it.
-    private int mMinContentWidth;
-
     // Need to have the separate control for horizontal and vertical scrollbar 
     // style than the View's single scrollbar style
     private boolean mOverlayHorizontalScrollbar = true;
@@ -288,11 +276,9 @@
     private static final int NEVER_REMEMBER_PASSWORD = 2;
     private static final int SWITCH_TO_SHORTPRESS = 3;
     private static final int SWITCH_TO_LONGPRESS = 4;
-    private static final int RELEASE_SINGLE_TAP = 5;
     private static final int UPDATE_TEXT_ENTRY_ADAPTER = 6;
     private static final int SWITCH_TO_ENTER = 7;
     private static final int RESUME_WEBCORE_UPDATE = 8;
-    private static final int DISMISS_ZOOM_TUTORIAL = 9;
 
     //! arg1=x, arg2=y
     static final int SCROLL_TO_MSG_ID               = 10;
@@ -321,7 +307,7 @@
         "NEVER_REMEMBER_PASSWORD", // = 2;
         "SWITCH_TO_SHORTPRESS", // = 3;
         "SWITCH_TO_LONGPRESS", // = 4;
-        "RELEASE_SINGLE_TAP", // = 5;
+        "5",
         "UPDATE_TEXT_ENTRY_ADAPTER", // = 6;
         "SWITCH_TO_ENTER", // = 7;
         "RESUME_WEBCORE_UPDATE", // = 8;
@@ -346,13 +332,14 @@
     };
 
     // width which view is considered to be fully zoomed out
-    static final int ZOOM_OUT_WIDTH = 1024;
+    static final int ZOOM_OUT_WIDTH = 1008;
 
-    private static final float DEFAULT_MAX_ZOOM_SCALE = 2;
-    private static final float DEFAULT_MIN_ZOOM_SCALE = (float) 1/3;
+    private static final float DEFAULT_MAX_ZOOM_SCALE = 4.0f;
+    private static final float DEFAULT_MIN_ZOOM_SCALE = 0.25f;
     // scale limit, which can be set through viewport meta tag in the web page
     private float mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
     private float mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+    private boolean mMinZoomScaleFixed = false;
 
     // initial scale in percent. 0 means using default.
     private int mInitialScale = 0;
@@ -562,8 +549,8 @@
 
     private void initZoomController(Context context) {
         // Create the buttons controller
-        mZoomButtonsController = new ZoomButtonsController(context, this);
-        mZoomButtonsController.setCallback(mZoomListener);
+        mZoomButtonsController = new ZoomButtonsController(this);
+        mZoomButtonsController.setOnZoomListener(mZoomListener);
 
         // Create the accessory buttons
         LayoutInflater inflater =
@@ -611,12 +598,6 @@
         final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         mTouchSlopSquare = slop * slop;
         mMinLockSnapReverseDistance = slop;
-        // use twice the line height, 32 based on our current default font, for
-        // the double tap slop as the ViewConfiguration's double tap slop, 100,
-        // is too big for the Browser
-        final int doubleTapslop = (int) (32 * getContext().getResources()
-                .getDisplayMetrics().density);
-        mDoubleTapSlopSquare = doubleTapslop * doubleTapslop;
         // use one line height, 16 based on our current default font, for how
         // far we allow a touch be away from the edge of a link
         mNavSlop = (int) (16 * getContext().getResources()
@@ -1646,8 +1627,7 @@
      * @return true if new values were sent
      */
     private boolean sendViewSizeZoom() {
-        int viewWidth = getViewWidth();
-        int newWidth = Math.round(viewWidth * mInvActualScale);
+        int newWidth = Math.round(getViewWidth() * mInvActualScale);
         int newHeight = Math.round(getViewHeight() * mInvActualScale);
         /*
          * Because the native side may have already done a layout before the
@@ -1663,7 +1643,7 @@
         // Avoid sending another message if the dimensions have not changed.
         if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) {
             mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED,
-                    newWidth, newHeight, new Integer(viewWidth));
+                    newWidth, newHeight, new Float(mActualScale));
             mLastWidthSent = newWidth;
             mLastHeightSent = newHeight;
             return true;
@@ -3341,19 +3321,10 @@
         mZoomCenterX = getViewWidth() * .5f;
         mZoomCenterY = getViewHeight() * .5f;
 
-        // update mMinZoomScale
-        if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
-            boolean atMin = Math.abs(mActualScale - mMinZoomScale) < 0.01f;
-            mMinZoomScale = (float) getViewWidth() / mContentWidth;
-            if (atMin) {
-                // if the WebView was at the minimum zoom scale, keep it. e,g.,
-                // the WebView was at the minimum zoom scale at the portrait
-                // mode, rotate it to the landscape modifying the scale to the
-                // new minimum zoom scale, when rotating back, we would like to
-                // keep the minimum zoom scale instead of keeping the same scale
-                // as normally we do.
-                mActualScale = mMinZoomScale;
-            }
+        // update mMinZoomScale if the minimum zoom scale is not fixed
+        if (!mMinZoomScaleFixed) {
+            mMinZoomScale = (float) getViewWidth()
+                    / Math.max(ZOOM_OUT_WIDTH, mContentWidth);
         }
 
         // we always force, in case our height changed, in which case we still
@@ -3411,15 +3382,6 @@
             return false;
         }
 
-        if (mShowZoomTutorial && getSettings().supportZoom()
-                && (mMaxZoomScale != mMinZoomScale)) {
-            ZoomButtonsController.showZoomTutorialOnce(mContext);
-            mShowZoomTutorial = false;
-            mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                    .obtainMessage(DISMISS_ZOOM_TUTORIAL),
-                    ZOOM_TUTORIAL_DURATION);
-        }
-
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, ev + " at " + ev.getEventTime() + " mTouchMode="
                     + mTouchMode);
@@ -3482,29 +3444,6 @@
                     nativeMoveSelection(viewToContent(mSelectX)
                             , viewToContent(mSelectY), false);
                     mTouchSelection = mExtendSelection = true;
-                } else if (!ZoomButtonsController.useOldZoom(mContext)
-                        && mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
-                    mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
-                    if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
-                        // Found doubletap, invoke the zoom controller
-                        int contentX = viewToContent((int) mLastTouchX
-                                + mScrollX);
-                        int contentY = viewToContent((int) mLastTouchY
-                                + mScrollY);
-                        if (inEditingMode()) {
-                            mTextEntry.updateCachedTextfield();
-                        }
-                        nativeClearFocus(contentX, contentY);
-                        if (mLogEvent) {
-                            EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
-                                    (eventTime - mLastTouchUpTime), eventTime);
-                        }
-                        return mZoomButtonsController.handleDoubleTapEvent(ev);
-                    } else {
-                        // commit the short press action
-                        doShortPress();
-                        // continue, mTouchMode should be still TOUCH_INIT_MODE
-                    }
                 } else {
                     mTouchMode = TOUCH_INIT_MODE;
                     mPreventDrag = mForwardTouchEvents;
@@ -3588,6 +3527,12 @@
                         mWebViewCore
                                 .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
                     }
+                    if (getSettings().supportZoom()
+                            && !mZoomButtonsController.isVisible()
+                            && (canZoomScrollOut() || 
+                                    mMinZoomScale < mMaxZoomScale)) {
+                        mZoomButtonsController.setVisible(true);
+                    }
                 }
 
                 // do pan
@@ -3660,16 +3605,12 @@
                 mLastTouchUpTime = eventTime;
                 switch (mTouchMode) {
                     case TOUCH_INIT_MODE: // tap
+                    case TOUCH_SHORTPRESS_START_MODE:
+                    case TOUCH_SHORTPRESS_MODE:
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                        if (getSettings().supportZoom()) {
-                            mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                                    .obtainMessage(RELEASE_SINGLE_TAP),
-                                    DOUBLE_TAP_TIMEOUT);
-                        } else {
-                            // do short press now
-                            mTouchMode = TOUCH_DONE_MODE;
-                            doShortPress();
-                        }
+                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                        mTouchMode = TOUCH_DONE_MODE;
+                        doShortPress();
                         break;
                     case TOUCH_SELECT_MODE:
                         commitCopy();
@@ -3697,28 +3638,6 @@
                             invalidate();
                         }
                         break;
-                    case TOUCH_SHORTPRESS_START_MODE:
-                    case TOUCH_SHORTPRESS_MODE: {
-                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                        if (eventTime - mLastTouchTime < TAP_TIMEOUT
-                                && getSettings().supportZoom()) {
-                            // Note: window manager will not release ACTION_UP
-                            // until all the previous action events are
-                            // returned. If GC happens, it can cause
-                            // SWITCH_TO_SHORTPRESS message fired before
-                            // ACTION_UP sent even time stamp of ACTION_UP is
-                            // less than the tap time out. We need to treat this
-                            // as tap instead of short press.
-                            mTouchMode = TOUCH_INIT_MODE;
-                            mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                                    .obtainMessage(RELEASE_SINGLE_TAP),
-                                    DOUBLE_TAP_TIMEOUT);
-                        } else {
-                            mTouchMode = TOUCH_DONE_MODE;
-                            doShortPress();
-                        }
-                        break;
-                    }
                     case TOUCH_DRAG_MODE:
                         // if the user waits a while w/o moving before the
                         // up, we don't want to do a fling
@@ -3759,7 +3678,6 @@
                 }
                 mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                 mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
                 mTouchMode = TOUCH_DONE_MODE;
                 int contentX = viewToContent((int) mLastTouchX + mScrollX);
                 int contentY = viewToContent((int) mLastTouchY + mScrollY);
@@ -4132,31 +4050,7 @@
         }
     }
 
-    /**
-     * An InvisibleView is an invisible, zero-sized View for backwards
-     * compatibility
-     */
-    private final class InvisibleView extends View {
-
-        private InvisibleView(Context context) {
-            super(context);
-            setVisibility(GONE);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(0, 0);
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-        }
-
-        @Override
-        protected void dispatchDraw(Canvas canvas) {
-        }
-    }
-
+    // TODO: deprecate
     /**
      * Returns a view containing zoom controls i.e. +/- buttons. The caller is
      * in charge of installing this view to the view hierarchy. This view will
@@ -4167,7 +4061,19 @@
      * an invisible dummy view for backwards compatibility.
      */
     public View getZoomControls() {
-        return new InvisibleView(mContext);
+        return mZoomButtonsController.getDummyZoomControls();
+    }
+
+    /**
+     * Gets the {@link ZoomButtonsController} which can be used to add
+     * additional buttons to the zoom controls window.
+     * 
+     * @return The instance of {@link ZoomButtonsController} used by this class,
+     *         or null if it is unavailable.
+     * @hide pending API council
+     */
+    public ZoomButtonsController getZoomButtonsController() {
+        return mZoomButtonsController;
     }
 
     /**
@@ -4447,11 +4353,6 @@
                     updateTextEntry();
                     break;
                 }
-                case RELEASE_SINGLE_TAP: {
-                    mTouchMode = TOUCH_DONE_MODE;
-                    doShortPress();
-                    break;
-                }
                 case SWITCH_TO_ENTER:
                     if (LOGV_ENABLED) Log.v(LOGTAG, "SWITCH_TO_ENTER");
                     mTouchMode = TOUCH_DONE_MODE;
@@ -4498,10 +4399,9 @@
                                     0, 0);
                         }
                     }
-                    mMinContentWidth = msg.arg1;
-                    if (mMinContentWidth > MAX_FLOAT_CONTENT_WIDTH) {
+                    if (!mMinZoomScaleFixed) {
                         mMinZoomScale = (float) getViewWidth()
-                                / draw.mWidthHeight.x;
+                                / Math.max(ZOOM_OUT_WIDTH, draw.mWidthHeight.x);
                     }
                     // We update the layout (i.e. request a layout from the
                     // view system) if the last view size that we sent to
@@ -4561,8 +4461,10 @@
                     int minScale = (Integer) scaleLimit.get("minScale");
                     if (minScale == 0) {
                         mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+                        mMinZoomScaleFixed = false;
                     } else {
                         mMinZoomScale = (float) (minScale / 100.0);
+                        mMinZoomScaleFixed = true;
                     }
                     int maxScale = (Integer) scaleLimit.get("maxScale");
                     if (maxScale == 0) {
@@ -4690,10 +4592,6 @@
                     }
                     break;
 
-                case DISMISS_ZOOM_TUTORIAL:
-                    mZoomButtonsController.finishZoomTutorial();
-                    break;
-
                 default:
                     super.handleMessage(msg);
                     break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index e10ffa1..3e4daf7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -725,7 +725,7 @@
 
                         case VIEW_SIZE_CHANGED:
                             viewSizeChanged(msg.arg1, msg.arg2,
-                                    ((Integer) msg.obj).intValue());
+                                    ((Float) msg.obj).floatValue());
                             break;
 
                         case SET_SCROLL_OFFSET:
@@ -1181,23 +1181,16 @@
     private int mCurrentViewWidth = 0;
     private int mCurrentViewHeight = 0;
 
-    // Define a minimum screen width so that we won't wrap the paragraph to one
-    // word per line during zoom-in.
-    private static final int MIN_SCREEN_WIDTH = 160;
-
     // notify webkit that our virtual view size changed size (after inv-zoom)
-    private void viewSizeChanged(int w, int h, int viewWidth) {
+    private void viewSizeChanged(int w, int h, float scale) {
         if (LOGV_ENABLED) Log.v(LOGTAG, "CORE onSizeChanged");
         if (w == 0) {
             Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
             return;
         }
-        // negative scale indicate that WebCore should reuse the current scale
-        float scale = (float) viewWidth / w;
         if (mSettings.getUseWideViewPort()
                 && (w < mViewportWidth || mViewportWidth == -1)) {
             int width = mViewportWidth;
-            int screenWidth = Math.max(w, MIN_SCREEN_WIDTH);
             if (mViewportWidth == -1) {
                 if (mSettings.getLayoutAlgorithm() == 
                         WebSettings.LayoutAlgorithm.NORMAL) {
@@ -1215,19 +1208,11 @@
                      * In the worse case, the native width will be adjusted when
                      * next zoom or screen orientation change happens.
                      */
-                    int minContentWidth = nativeGetContentMinPrefWidth();
-                    if (minContentWidth > WebView.MAX_FLOAT_CONTENT_WIDTH) {
-                        // keep the same width and screen width so that there is 
-                        // no reflow when zoom-out
-                        width = minContentWidth;
-                        screenWidth = Math.min(screenWidth, Math.abs(viewWidth));
-                    } else {
-                        width = Math.max(w, minContentWidth);
-                    }
+                    width = Math.max(w, nativeGetContentMinPrefWidth());
                 }
             }
-            nativeSetSize(width, Math.round((float) width * h / w),
-                    screenWidth, scale, w, h);
+            nativeSetSize(width, Math.round((float) width * h / w), w, scale,
+                    w, h);
         } else {
             nativeSetSize(w, h, w, scale, w, h);
         }
@@ -1289,10 +1274,7 @@
             draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
             if (LOGV_ENABLED) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.NEW_PICTURE_MSG_ID,
-                    mViewportMinimumScale == 0 ? nativeGetContentMinPrefWidth()
-                            : 0,
-                    0, draw).sendToTarget();
+                    WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
             if (mWebkitScrollX != 0 || mWebkitScrollY != 0) {
                 // as we have the new picture, try to sync the scroll position
                 Message.obtain(mWebView.mPrivateHandler,
@@ -1533,11 +1515,11 @@
         // white space in the GMail which uses WebView for message view.
         if (mWebView != null && mWebView.mHeightCanMeasure) {
             mWebView.mLastHeightSent = 0;
-            // Send a negative screen width to indicate that WebCore should 
-            // reuse the current scale
+            // Send a negative scale to indicate that WebCore should reuse the
+            // current scale
             mEventHub.sendMessage(Message.obtain(null,
                     EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
-                    mWebView.mLastHeightSent, -mWebView.mLastWidthSent));
+                    mWebView.mLastHeightSent, -1.0f));
         }
 
         mBrowserFrame.didFirstLayout();
diff --git a/core/java/android/webkit/gears/DesktopAndroid.java b/core/java/android/webkit/gears/DesktopAndroid.java
index ee8ca49..a7a144b 100644
--- a/core/java/android/webkit/gears/DesktopAndroid.java
+++ b/core/java/android/webkit/gears/DesktopAndroid.java
@@ -31,6 +31,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.provider.Browser;
 import android.util.Log;
 import android.webkit.WebView;
 
@@ -78,7 +79,10 @@
 
     Intent viewWebPage = new Intent(Intent.ACTION_VIEW);
     viewWebPage.setData(Uri.parse(url));
-    viewWebPage.addCategory(Intent.CATEGORY_BROWSABLE);
+    long urlHash = url.hashCode();
+    long uniqueId = (urlHash << 32) | viewWebPage.hashCode();
+    viewWebPage.putExtra(Browser.EXTRA_APPLICATION_ID,
+            Long.toString(uniqueId));
 
     Intent intent = new Intent(ACTION_INSTALL_SHORTCUT);
     intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, viewWebPage);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 7fc96fc..bd4bba8f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -982,6 +982,18 @@
         mSelectorRect.setEmpty();
         invalidate();
     }
+    
+    /**
+     * The list is empty and we need to change the layout, so *really* clear everything out.
+     * @hide - for AutoCompleteTextView & SearchDialog only
+     */
+    /* package */ void resetListAndClearViews() {
+        rememberSyncState();
+        removeAllViewsInLayout();
+        mRecycler.clear();
+        mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
+        requestLayout();
+    }
 
     @Override
     protected int computeVerticalScrollExtent() {
@@ -1422,7 +1434,10 @@
 
             final View v = getChildAt(mSelectedPosition - mFirstPosition);
 
-            if (v != null) v.setPressed(true);
+            if (v != null) {
+                if (v.hasFocusable()) return;
+                v.setPressed(true);
+            }
             setPressed(true);
 
             final boolean longClickable = isLongClickable();
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 7b9670b..e613541 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -630,6 +630,16 @@
     }
     
     /**
+     * We're changing the adapter and its views so really, really clear everything out
+     * @hide - for SearchDialog only
+     */
+    public void resetListAndClearViews() {
+        if (mDropDownList != null) {
+            mDropDownList.resetListAndClearViews();
+        }
+    }
+
+    /**
      * <p>Starts filtering the content of the drop down list. The filtering
      * pattern is the content of the edit box. Subclasses should override this
      * method to filter with a different pattern, for instance a substring of
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index f646ab5..441414a 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -763,7 +763,7 @@
     @Override
     public void invalidateDrawable(Drawable dr) {
         if (!mInDrawing) {
-            if (dr == mProgressDrawable || dr == mIndeterminateDrawable) {
+            if (verifyDrawable(dr)) {
                 final Rect dirty = dr.getBounds();
                 final int scrollX = mScrollX + mPaddingLeft;
                 final int scrollY = mScrollY + mPaddingTop;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 426d711..7b62b50 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6208,7 +6208,7 @@
             return superResult;
         }
 
-        if (mMovement != null && mText instanceof Spannable && mLayout != null) {
+        if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
             
             if (action == MotionEvent.ACTION_DOWN) {
                 mScrolled = false;
@@ -6219,7 +6219,9 @@
             int oldSelStart = Selection.getSelectionStart(mText);
             int oldSelEnd = Selection.getSelectionEnd(mText);
             
-            handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
+            if (mMovement != null) {
+                handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
+            }
 
             if (mText instanceof Editable && onCheckIsTextEditor()) {
                 if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 6729fd1..4daa419 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -24,12 +24,15 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.util.Log;
+import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -37,31 +40,51 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewRoot;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.View.OnClickListener;
 import android.view.WindowManager.LayoutParams;
 
-// TODO: make sure no px values exist, only dip (scale if necessary from Viewconfiguration)
-
+/*
+ * Implementation notes:
+ * - The zoom controls are displayed in their own window.
+ *   (Easier for the client and better performance)
+ * - This window is not touchable, and by default is not focusable.
+ * - To make the buttons clickable, it attaches a OnTouchListener to the owner
+ *   view and does the hit detection locally.
+ * - When it is focusable, it forwards uninteresting events to the owner view's
+ *   view hierarchy.
+ */
 /**
- * TODO: Docs
- *
+ * The {@link ZoomButtonsController} handles showing and hiding the zoom
+ * controls relative to an owner view. It also gives the client access to the
+ * zoom controls container, allowing for additional accessory buttons to be
+ * shown in the zoom controls window.
+ * <p>
+ * Typical usage involves the client using the {@link GestureDetector} to
+ * forward events from
+ * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)} to
+ * {@link #handleDoubleTapEvent(MotionEvent)}. Also, whenever the owner cannot
+ * be zoomed further, the client should update
+ * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}.
+ * <p>
  * If you are using this with a custom View, please call
  * {@link #setVisible(boolean) setVisible(false)} from the
  * {@link View#onDetachedFromWindow}.
- *
+ * 
  * @hide
  */
-public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyListener {
+public class ZoomButtonsController implements View.OnTouchListener {
 
     private static final String TAG = "ZoomButtonsController";
 
     private static final int ZOOM_CONTROLS_TIMEOUT =
             (int) ViewConfiguration.getZoomControlsTimeout();
 
-    // TODO: scaled to density
     private static final int ZOOM_CONTROLS_TOUCH_PADDING = 20;
+    private int mTouchPaddingScaledSq;
 
     private Context mContext;
     private WindowManager mWindowManager;
@@ -72,17 +95,17 @@
     private View mOwnerView;
 
     /**
-     * The bounds of the owner view in global coordinates. This is recalculated
+     * The location of the owner view on the screen. This is recalculated
      * each time the zoom controller is shown.
      */
-    private Rect mOwnerViewBounds = new Rect();
+    private int[] mOwnerViewRawLocation = new int[2];
 
     /**
      * The container that is added as a window.
      */
     private FrameLayout mContainer;
     private LayoutParams mContainerLayoutParams;
-    private int[] mContainerLocation = new int[2];
+    private int[] mContainerRawLocation = new int[2];
 
     private ZoomControls mControls;
 
@@ -94,7 +117,7 @@
     /**
      * The {@link #mTouchTargetView}'s location in window, set on touch down.
      */
-    private int[] mTouchTargetLocationInWindow = new int[2];
+    private int[] mTouchTargetWindowLocation = new int[2];
     /**
      * If the zoom controller is dismissed but the user is still in a touch
      * interaction, we set this to true. This will ignore all touch events until
@@ -102,15 +125,28 @@
      */
     private boolean mReleaseTouchListenerOnUp;
 
+    /**
+     * Whether we are currently in the double-tap gesture, with the second tap
+     * still being performed (i.e., we're waiting for the second tap's touch up).
+     */
     private boolean mIsSecondTapDown;
 
+    /** Whether the container has been added to the window manager. */
     private boolean mIsVisible;
 
     private Rect mTempRect = new Rect();
-
+    private int[] mTempIntArray = new int[2];
+    
     private OnZoomListener mCallback;
 
     /**
+     * In 1.0, the ZoomControls were to be added to the UI by the client of
+     * WebView, MapView, etc. We didn't want apps to break, so we return a dummy
+     * view in place now.
+     */
+    private InvisibleView mDummyZoomControls;
+    
+    /**
      * When showing the zoom, we add the view as a new window. However, there is
      * logic that needs to know the size of the zoom which is determined after
      * it's laid out. Therefore, we must post this logic onto the UI thread so
@@ -121,6 +157,9 @@
     private IntentFilter mConfigurationChangedFilter =
             new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
 
+    /**
+     * Needed to reposition the zoom controls after configuration changes.
+     */
     private BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -161,41 +200,68 @@
 
                 case MSG_POST_SET_VISIBLE:
                     if (mOwnerView.getWindowToken() == null) {
-                        // Doh, it is still null, throw an exception
-                        throw new IllegalArgumentException(
+                        // Doh, it is still null, just ignore the set visible call
+                        Log.e(TAG,
                                 "Cannot make the zoom controller visible if the owner view is " +
                                 "not attached to a window.");
+                    } else {
+                        setVisible(true);
                     }
-                    setVisible(true);
                     break;
             }
 
         }
     };
 
-    public ZoomButtonsController(Context context, View ownerView) {
-        mContext = context;
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+    /**
+     * Constructor for the {@link ZoomButtonsController}.
+     * 
+     * @param ownerView The view that is being zoomed by the zoom controls. The
+     *            zoom controls will be displayed aligned with this view.
+     */
+    public ZoomButtonsController(View ownerView) {
+        mContext = ownerView.getContext();
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mOwnerView = ownerView;
 
+        mTouchPaddingScaledSq = (int)
+                (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density);
+        mTouchPaddingScaledSq *= mTouchPaddingScaledSq;
+        
         mContainer = createContainer();
     }
 
+    /**
+     * Whether to enable the zoom in control.
+     * 
+     * @param enabled Whether to enable the zoom in control.
+     */
     public void setZoomInEnabled(boolean enabled) {
         mControls.setIsZoomInEnabled(enabled);
     }
 
+    /**
+     * Whether to enable the zoom out control.
+     * 
+     * @param enabled Whether to enable the zoom out control.
+     */
     public void setZoomOutEnabled(boolean enabled) {
         mControls.setIsZoomOutEnabled(enabled);
     }
 
+    /**
+     * Sets the delay between zoom callbacks as the user holds a zoom button.
+     * 
+     * @param speed The delay in milliseconds between zoom callbacks.
+     */
     public void setZoomSpeed(long speed) {
         mControls.setZoomSpeed(speed);
     }
 
     private FrameLayout createContainer() {
         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-        lp.gravity = Gravity.BOTTOM | Gravity.CENTER;
+        // Controls are positioned BOTTOM | CENTER with respect to the owner view.
+        lp.gravity = Gravity.TOP | Gravity.LEFT;
         lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
                 LayoutParams.FLAG_NOT_FOCUSABLE |
                 LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -206,10 +272,9 @@
         lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons;
         mContainerLayoutParams = lp;
 
-        FrameLayout container = new FrameLayout(mContext);
+        FrameLayout container = new Container(mContext);
         container.setLayoutParams(lp);
         container.setMeasureAllChildren(true);
-        container.setOnKeyListener(this);
 
         LayoutInflater inflater = (LayoutInflater) mContext
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -232,30 +297,51 @@
         return container;
     }
 
-    public void setCallback(OnZoomListener callback) {
-        mCallback = callback;
+    /**
+     * Sets the {@link OnZoomListener} listener that receives callbacks to zoom.
+     * 
+     * @param listener The listener that will be told to zoom.
+     */
+    public void setOnZoomListener(OnZoomListener listener) {
+        mCallback = listener;
     }
 
+    /**
+     * Sets whether the zoom controls should be focusable. If the controls are
+     * focusable, then trackball and arrow key interactions are possible.
+     * Otherwise, only touch interactions are possible.
+     * 
+     * @param focusable Whether the zoom controls should be focusable.
+     */
     public void setFocusable(boolean focusable) {
+        int oldFlags = mContainerLayoutParams.flags;
         if (focusable) {
             mContainerLayoutParams.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
         } else {
             mContainerLayoutParams.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
         }
 
-        if (mIsVisible) {
+        if ((mContainerLayoutParams.flags != oldFlags) && mIsVisible) {
             mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
         }
     }
 
+    /**
+     * Whether the zoom controls are visible to the user.
+     * 
+     * @return Whether the zoom controls are visible to the user.
+     */
     public boolean isVisible() {
         return mIsVisible;
     }
 
+    /**
+     * Sets whether the zoom controls should be visible to the user.
+     * 
+     * @param visible Whether the zoom controls should be visible to the user.
+     */
     public void setVisible(boolean visible) {
 
-        if (!useThisZoom(mContext)) return;
-
         if (visible) {
             if (mOwnerView.getWindowToken() == null) {
                 /*
@@ -329,12 +415,13 @@
     }
 
     /**
-     * TODO: docs
-     *
-     * Notes:
-     * - Please ensure you set your View to INVISIBLE not GONE when hiding it.
-     *
-     * @return TODO
+     * Gets the container that is the parent of the zoom controls.
+     * <p>
+     * The client can add other views to this container to link them with the
+     * zoom controls.
+     * 
+     * @return The container of the zoom controls. It will be a layout that
+     *         respects the gravity of a child's layout parameters.
      */
     public ViewGroup getContainer() {
         return mContainer;
@@ -347,14 +434,12 @@
 
     /**
      * Should be called by the client for each event belonging to the second tap
-     * (the down, move, up, and cancel events).
+     * (the down, move, up, and/or cancel events).
      *
      * @param event The event belonging to the second tap.
      * @return Whether the event was consumed.
      */
     public boolean handleDoubleTapEvent(MotionEvent event) {
-        if (!useThisZoom(mContext)) return false;
-
         int action = event.getAction();
 
         if (action == MotionEvent.ACTION_DOWN) {
@@ -382,9 +467,28 @@
     }
 
     private void refreshPositioningVariables() {
+        // Position the zoom controls on the bottom of the owner view.
+        int ownerHeight = mOwnerView.getHeight();
+        int ownerWidth = mOwnerView.getWidth();
+        // The gap between the top of the owner and the top of the container
+        int containerOwnerYOffset = ownerHeight - mContainer.getHeight();
+
         // Calculate the owner view's bounds
-        mOwnerView.getGlobalVisibleRect(mOwnerViewBounds);
-        mContainer.getLocationOnScreen(mContainerLocation);
+        mOwnerView.getLocationOnScreen(mOwnerViewRawLocation);
+        mContainerRawLocation[0] = mOwnerViewRawLocation[0];
+        mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset;
+        
+        int[] ownerViewWindowLoc = mTempIntArray;
+        mOwnerView.getLocationInWindow(ownerViewWindowLoc);
+
+        // lp.x and lp.y should be relative to the owner's window top-left
+        mContainerLayoutParams.x = ownerViewWindowLoc[0];
+        mContainerLayoutParams.width = ownerWidth;
+        mContainerLayoutParams.y = ownerViewWindowLoc[1] + containerOwnerYOffset;
+        if (mIsVisible) {
+            mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
+        }
+        
     }
 
     /**
@@ -396,11 +500,65 @@
         }
     }
 
-    public boolean onKey(View v, int keyCode, KeyEvent event) {
-        dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
-        return false;
+    /* This will only be called when the container has focus. */
+    private boolean onContainerKey(KeyEvent event) {
+        int keyCode = event.getKeyCode();
+        if (isInterestingKey(keyCode)) {
+            
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                setVisible(false);
+            } else {
+                dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
+            }
+            
+            // Let the container handle the key
+            return false;
+            
+        } else {
+            
+            ViewRoot viewRoot = getOwnerViewRoot();
+            if (viewRoot != null) {
+                viewRoot.dispatchKey(event);
+            }
+            
+            // We gave the key to the owner, don't let the container handle this key
+            return true;
+        }
     }
 
+    private boolean isInterestingKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_BACK:
+                return true;
+            default:
+                return false;
+        }
+    }
+    
+    private ViewRoot getOwnerViewRoot() {
+        View rootViewOfOwner = mOwnerView.getRootView();
+        if (rootViewOfOwner == null) {
+            return null;
+        }
+        
+        ViewParent parentOfRootView = rootViewOfOwner.getParent();
+        if (parentOfRootView instanceof ViewRoot) {
+            return (ViewRoot) parentOfRootView;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @hide The ZoomButtonsController implements the OnTouchListener, but this
+     *       does not need to be shown in its public API.
+     */
     public boolean onTouch(View v, MotionEvent event) {
         int action = event.getAction();
 
@@ -423,14 +581,13 @@
             return true;
         }
 
-        // TODO: optimize this (it ends up removing message and queuing another)
         dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
 
         View targetView = mTouchTargetView;
 
         switch (action) {
             case MotionEvent.ACTION_DOWN:
-                targetView = getViewForTouch((int) event.getRawX(), (int) event.getRawY());
+                targetView = findViewForTouch((int) event.getRawX(), (int) event.getRawY());
                 setTouchTargetView(targetView);
                 break;
 
@@ -442,14 +599,22 @@
 
         if (targetView != null) {
             // The upperleft corner of the target view in raw coordinates
-            int targetViewRawX = mContainerLocation[0] + mTouchTargetLocationInWindow[0];
-            int targetViewRawY = mContainerLocation[1] + mTouchTargetLocationInWindow[1];
+            int targetViewRawX = mContainerRawLocation[0] + mTouchTargetWindowLocation[0];
+            int targetViewRawY = mContainerRawLocation[1] + mTouchTargetWindowLocation[1];
 
             MotionEvent containerEvent = MotionEvent.obtain(event);
             // Convert the motion event into the target view's coordinates (from
             // owner view's coordinates)
-            containerEvent.offsetLocation(mOwnerViewBounds.left - targetViewRawX,
-                    mOwnerViewBounds.top - targetViewRawY);
+            containerEvent.offsetLocation(mOwnerViewRawLocation[0] - targetViewRawX,
+                    mOwnerViewRawLocation[1] - targetViewRawY);
+            /* Disallow negative coordinates (which can occur due to
+             * ZOOM_CONTROLS_TOUCH_PADDING) */
+            if (containerEvent.getX() < 0) {
+                containerEvent.offsetLocation(-containerEvent.getX(), 0);
+            }
+            if (containerEvent.getY() < 0) {
+                containerEvent.offsetLocation(0, -containerEvent.getY());
+            }
             boolean retValue = targetView.dispatchTouchEvent(containerEvent);
             containerEvent.recycle();
             return retValue || consumeEvent;
@@ -462,7 +627,7 @@
     private void setTouchTargetView(View view) {
         mTouchTargetView = view;
         if (view != null) {
-            view.getLocationInWindow(mTouchTargetLocationInWindow);
+            view.getLocationInWindow(mTouchTargetWindowLocation);
         }
     }
 
@@ -473,11 +638,15 @@
      * @param rawY The raw Y.
      * @return The view that should receive the touches, or null if there is not one.
      */
-    private View getViewForTouch(int rawX, int rawY) {
+    private View findViewForTouch(int rawX, int rawY) {
         // Reverse order so the child drawn on top gets first dibs.
-        int containerCoordsX = rawX - mContainerLocation[0];
-        int containerCoordsY = rawY - mContainerLocation[1];
+        int containerCoordsX = rawX - mContainerRawLocation[0];
+        int containerCoordsY = rawY - mContainerRawLocation[1];
         Rect frame = mTempRect;
+
+        View closestChild = null;
+        int closestChildDistanceSq = Integer.MAX_VALUE;
+        
         for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
             View child = mContainer.getChildAt(i);
             if (child.getVisibility() != View.VISIBLE) {
@@ -485,14 +654,24 @@
             }
 
             child.getHitRect(frame);
-            // Expand the touch region
-            frame.top -= ZOOM_CONTROLS_TOUCH_PADDING;
             if (frame.contains(containerCoordsX, containerCoordsY)) {
                 return child;
             }
+            
+            int distanceX = Math.min(Math.abs(frame.left - containerCoordsX),
+                    Math.abs(containerCoordsX - frame.right));
+            int distanceY = Math.min(Math.abs(frame.top - containerCoordsY),
+                    Math.abs(containerCoordsY - frame.bottom));
+            int distanceSq = distanceX * distanceX + distanceY * distanceY;
+                        
+            if ((distanceSq < mTouchPaddingScaledSq) &&
+                    (distanceSq < closestChildDistanceSq)) {
+                closestChild = child;
+                closestChildDistanceSq = distanceSq;
+            }
         }
 
-        return null;
+        return closestChild;
     }
 
     private void onPostConfigurationChanged() {
@@ -518,6 +697,10 @@
      *       gallery
      */
     public static void showZoomTutorialOnce(Context context) {
+        
+        // TODO: remove this code, but to hit the weekend build, just never show
+        if (true) return;
+        
         ContentResolver cr = context.getContentResolver();
         if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) {
             return;
@@ -583,22 +766,83 @@
         finishZoomTutorial(mContext, true);
     }
 
-    // Temporary methods for different zoom types
-    static int getZoomType(Context context) {
-        return Settings.System.getInt(context.getContentResolver(), "zoom", 2);
+    /** @hide Should only be used only be WebView and MapView */
+    public View getDummyZoomControls() {
+        if (mDummyZoomControls == null) {
+            mDummyZoomControls = new InvisibleView(mContext);
+        }
+        return mDummyZoomControls;
     }
-
-    public static boolean useOldZoom(Context context) {
-        return getZoomType(context) == 0;
-    }
-
-    public static boolean useThisZoom(Context context) {
-        return getZoomType(context) == 2;
-    }
-
+    
+    /**
+     * Interface that will be called when the user performs an interaction that
+     * triggers some action, for example zooming.
+     */
     public interface OnZoomListener {
+        /**
+         * Called when the given point should be centered. The point will be in
+         * owner view coordinates.
+         * 
+         * @param x The x of the point.
+         * @param y The y of the point.
+         */
         void onCenter(int x, int y);
+        
+        /**
+         * Called when the zoom controls' visibility changes.
+         * 
+         * @param visible Whether the zoom controls are visible.
+         */
         void onVisibilityChanged(boolean visible);
+        
+        /**
+         * Called when the owner view needs to be zoomed.
+         * 
+         * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out.
+         */
         void onZoom(boolean zoomIn);
     }
+    
+    private class Container extends FrameLayout {
+        public Container(Context context) {
+            super(context);
+        }
+
+        /*
+         * Need to override this to intercept the key events. Otherwise, we
+         * would attach a key listener to the container but its superclass
+         * ViewGroup gives it to the focused View instead of calling the key
+         * listener, and so we wouldn't get the events.
+         */
+        @Override
+        public boolean dispatchKeyEvent(KeyEvent event) {
+            return onContainerKey(event) ? true : super.dispatchKeyEvent(event);
+        }
+    }
+
+    /**
+     * An InvisibleView is an invisible, zero-sized View for backwards
+     * compatibility
+     */
+    private final class InvisibleView extends View {
+
+        private InvisibleView(Context context) {
+            super(context);
+            setVisibility(GONE);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(0, 0);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+        }
+    }
+
 }
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index e978db8..84d8f0e 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -29,8 +29,12 @@
 
 /**
  * The {@code ZoomControls} class displays a simple set of controls used for zooming and
- * provides callbacks to register for events.
- */
+ * provides callbacks to register for events. */
+// TODO: pending API council
+// * <p>
+// * Instead of using this directly, consider using the {@link ZoomButtonsController} which
+// * handles displaying the zoom controls.
+// */
 @Widget
 public class ZoomControls extends LinearLayout {
 
@@ -81,9 +85,7 @@
     }
     
     public void show() {
-        if (ZoomButtonsController.useOldZoom(mContext)) {
-            fade(View.VISIBLE, 0.0f, 1.0f);
-        }
+        fade(View.VISIBLE, 0.0f, 1.0f);
     }
     
     public void hide() {
diff --git a/core/java/com/android/internal/widget/EditStyledText.java b/core/java/com/android/internal/widget/EditStyledText.java
index 48b4780..8a4675a 100644
--- a/core/java/com/android/internal/widget/EditStyledText.java
+++ b/core/java/com/android/internal/widget/EditStyledText.java
@@ -16,20 +16,26 @@
 
 package com.android.internal.widget;
 
+import android.app.AlertDialog.Builder;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import android.os.Bundle;
 import android.text.Editable;
+import android.text.Html;
 import android.text.Spannable;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.ForegroundColorSpan;
+import android.text.style.ImageSpan;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.widget.EditText;
 
 /**
- * EditStyledText extends EditText for managing the flow and status 
- * to edit the styled text. This manages the states and flows of editing,
- * supports inserting image, import/export HTML.
+ * EditStyledText extends EditText for managing the flow and status to edit
+ * the styled text. This manages the states and flows of editing, supports
+ * inserting image, import/export HTML.
  */
 public class EditStyledText extends EditText {
 
@@ -61,7 +67,7 @@
     public static final int STATE_SELECT_ON = 1;
     /** The state that selection is done, but not fixed. */
     public static final int STATE_SELECTED = 2;
-    /** The state that selection is done and not fixed.*/
+    /** The state that selection is done and not fixed. */
     public static final int STATE_SELECT_FIX = 3;
 
     /**
@@ -73,26 +79,28 @@
     public static final int HINT_MSG_SELECT_END = 3;
     public static final int HINT_MSG_PUSH_COMPETE = 4;
 
-
     /**
-     * EditStyledTextInterface provides functions for notifying messages
-     * to calling class.
+     * EditStyledTextInterface provides functions for notifying messages to
+     * calling class.
      */
-    public interface EditStyledTextInterface {
-        public void notifyHintMsg(int msg_id);
+    public interface EditStyledTextNotifier {
+        public void notifyHintMsg(int msgId);
     }
-    private EditStyledTextInterface mESTInterface;
+
+    private EditStyledTextNotifier mESTInterface;
 
     /**
-     * EditStyledTextEditorManager manages the flow and status of 
-     * each function for editing styled text.
+     * EditStyledTextEditorManager manages the flow and status of each
+     * function for editing styled text.
      */
-    private EditStyledTextEditorManager mManager;
+    private EditorManager mManager;
+    private StyledTextConverter mConverter;
+    private StyledTextToast mToast;
 
     /**
-      * EditStyledText extends EditText for managing flow of each editing
-      * action.
-      */
+     * EditStyledText extends EditText for managing flow of each editing
+     * action.
+     */
     public EditStyledText(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         init();
@@ -109,11 +117,54 @@
     }
 
     /**
-     * Set View objects used in EditStyledText.
-     * @param helptext The view shows help messages.
+     * Set Notifier.
      */
-    public void setParts(EditStyledTextInterface est_interface) {
-        mESTInterface = est_interface;
+    public void setNotifier(EditStyledTextNotifier estInterface) {
+        mESTInterface = estInterface;
+    }
+
+    /**
+     * Set Builder for AlertDialog.
+     * 
+     * @param builder
+     *            Builder for opening Alert Dialog.
+     */
+    public void setBuilder(Builder builder) {
+        mToast.setBuilder(builder);
+    }
+
+    /**
+     * Set Parameters for ColorAlertDialog.
+     * 
+     * @param colortitle
+     *            Title for Alert Dialog.
+     * @param colornames
+     *            List of name of selecting color.
+     * @param colorints
+     *            List of int of color.
+     */
+    public void setColorAlertParams(CharSequence colortitle,
+            CharSequence[] colornames, CharSequence[] colorints) {
+        mToast.setColorAlertParams(colortitle, colornames, colorints);
+    }
+
+    /**
+     * Set Parameters for SizeAlertDialog.
+     * 
+     * @param sizetitle
+     *            Title for Alert Dialog.
+     * @param sizenames
+     *            List of name of selecting size.
+     * @param sizedisplayints
+     *            List of int of size displayed in TextView.
+     * @param sizesendints
+     *            List of int of size exported to HTML.
+     */
+    public void setSizeAlertParams(CharSequence sizetitle,
+            CharSequence[] sizenames, CharSequence[] sizedisplayints,
+            CharSequence[] sizesendints) {
+        mToast.setSizeAlertParams(sizetitle, sizenames, sizedisplayints,
+                sizesendints);
     }
 
     @Override
@@ -129,8 +180,8 @@
     }
 
     /**
-     * Start editing. This function have to be called before other
-     * editing actions.
+     * Start editing. This function have to be called before other editing
+     * actions.
      */
     public void onStartEdit() {
         mManager.onStartEdit();
@@ -186,6 +237,26 @@
     }
 
     /**
+     * InsertImage to TextView by using URI
+     * 
+     * @param uri
+     *            URI of the iamge inserted to TextView.
+     */
+    public void onInsertImage(Uri uri) {
+        mManager.onInsertImage(uri);
+    }
+
+    /**
+     * InsertImage to TextView by using resource ID
+     * 
+     * @param resId
+     *            Resource ID of the iamge inserted to TextView.
+     */
+    public void onInsertImage(int resId) {
+        mManager.onInsertImage(resId);
+    }
+
+    /**
      * Fix Selected Item.
      */
     public void fixSelectedItem() {
@@ -194,7 +265,9 @@
 
     /**
      * Set Size of the Item.
-     * @param size The size of the Item.
+     * 
+     * @param size
+     *            The size of the Item.
      */
     public void setItemSize(int size) {
         mManager.setItemSize(size);
@@ -202,14 +275,25 @@
 
     /**
      * Set Color of the Item.
-     * @param color The color of the Item.
+     * 
+     * @param color
+     *            The color of the Item.
      */
     public void setItemColor(int color) {
         mManager.setItemColor(color);
     }
 
+    public void onShowColorAlert() {
+        mToast.onShowColorAlertDialog();
+    }
+
+    public void onShowSizeAlert() {
+        mToast.onShowSizeAlertDialog();
+    }
+
     /**
      * Check editing is started.
+     * 
      * @return Whether editing is started or not.
      */
     public boolean isEditting() {
@@ -218,6 +302,7 @@
 
     /**
      * Get the mode of the action.
+     * 
      * @return The mode of the action.
      */
     public int getEditMode() {
@@ -226,12 +311,17 @@
 
     /**
      * Get the state of the selection.
+     * 
      * @return The state of the selection.
      */
     public int getSelectState() {
         return mManager.getSelectState();
     }
 
+    public String getBody() {
+        return mConverter.getConvertedBody();
+    }
+
     /**
      * Initialize members.
      */
@@ -240,23 +330,36 @@
             Log.d(LOG_TAG, "--- init");
             requestFocus();
         }
-        mManager = new EditStyledTextEditorManager(this);
+        mManager = new EditorManager(this);
+        mConverter = new StyledTextConverter(this);
+        mToast = new StyledTextToast(this);
     }
 
     /**
      * Notify hint messages what action is expected to calling class.
-     * @param msg
+     * 
+     * @param msgId
+     *            Id of the hint message.
      */
-    private void setHintMessage(int msg_id) {
+    private void setHintMessage(int msgId) {
         if (mESTInterface != null) {
-            mESTInterface.notifyHintMsg(msg_id);
+            mESTInterface.notifyHintMsg(msgId);
         }
     }
 
+    @Override
+    public Bundle getInputExtras(boolean create) {
+        Bundle bundle = super.getInputExtras(create);
+        if (bundle != null) {
+            bundle.putBoolean("allowEmoji", true);
+        }
+        return bundle;
+    }
+
     /**
      * Object which manages the flow and status of editing actions.
      */
-    private class EditStyledTextEditorManager {
+    private class EditorManager {
         private boolean mEditFlag = false;
         private int mMode = 0;
         private int mState = 0;
@@ -266,7 +369,7 @@
         private Editable mTextSelectBuffer;
         private CharSequence mTextCopyBufer;
 
-        EditStyledTextEditorManager(EditStyledText est) {
+        EditorManager(EditStyledText est) {
             mEST = est;
         }
 
@@ -368,6 +471,28 @@
             handleComplete();
         }
 
+        public void onInsertImage(Uri uri) {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- onInsertImage by URI: " + uri.getPath()
+                        + "," + uri.toString());
+            }
+
+            mEST.getText().append("a");
+            mEST.getText().setSpan(new ImageSpan(mEST.getContext(), uri),
+                    mEST.getText().length() - 1, mEST.getText().length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+
+        public void onInsertImage(int resID) {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- onInsertImage by resID");
+            }
+            mEST.getText().append("b");
+            mEST.getText().setSpan(new ImageSpan(mEST.getContext(), resID),
+                    mEST.getText().length() - 1, mEST.getText().length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        }
+
         public boolean isEditting() {
             return mEditFlag;
         }
@@ -404,6 +529,12 @@
             case MODE_COPY:
                 handleCopy();
                 break;
+            case MODE_COLOR:
+                handleColor();
+                break;
+            case MODE_SIZE:
+                handleSize();
+                break;
             default:
                 break;
             }
@@ -455,12 +586,14 @@
                 Log.d(LOG_TAG, "--- handleSize: " + mMode + "," + mState);
             }
             if (!mEditFlag) {
+                Log.e(LOG_TAG, "--- Editing is not started for handlesize.");
                 return;
             }
             if (mMode == MODE_NOTHING || mMode == MODE_SELECT) {
                 mMode = MODE_SIZE;
                 if (mState == STATE_SELECTED) {
                     mState = STATE_SELECT_FIX;
+                    handleSize();
                 } else {
                     handleSelect();
                 }
@@ -468,22 +601,29 @@
                 handleCancel();
                 mMode = MODE_SIZE;
                 handleSize();
-            } else if (mState == STATE_SELECT_FIX) {
-                mEST.setHintMessage(HINT_MSG_NULL);
+            } else {
+                if (mState == STATE_SELECT_FIX) {
+                    mEST.setHintMessage(HINT_MSG_NULL);
+                    mEST.onShowSizeAlert();
+                } else {
+                    Log.d(LOG_TAG, "--- handlesize: do nothing");
+                }
             }
         }
 
         private void handleColor() {
             if (DBG) {
-                Log.d(LOG_TAG, "--- handleColor");
+                Log.d(LOG_TAG, "--- handleSize: " + mMode + "," + mState);
             }
             if (!mEditFlag) {
+                Log.e(LOG_TAG, "--- Editing is not started for handlecolor.");
                 return;
             }
             if (mMode == MODE_NOTHING || mMode == MODE_SELECT) {
                 mMode = MODE_COLOR;
                 if (mState == STATE_SELECTED) {
                     mState = STATE_SELECT_FIX;
+                    handleColor();
                 } else {
                     handleSelect();
                 }
@@ -491,35 +631,39 @@
                 handleCancel();
                 mMode = MODE_COLOR;
                 handleSize();
-            } else if (mState == STATE_SELECT_FIX) {
-                mEST.setHintMessage(HINT_MSG_NULL);
+            } else {
+                if (mState == STATE_SELECT_FIX) {
+                    mEST.setHintMessage(HINT_MSG_NULL);
+                    mEST.onShowColorAlert();
+                } else {
+                    Log.d(LOG_TAG, "--- handlecolor: do nothing");
+                }
             }
         }
 
         private void handleSelect() {
             if (DBG) {
-                Log.d(LOG_TAG, "--- handleSelect" + mEditFlag + "," + mState);
+                Log.d(LOG_TAG, "--- handleSelect:" + mEditFlag + "," + mState);
             }
             if (!mEditFlag) {
                 return;
             }
             if (mState == STATE_SELECT_OFF) {
                 if (isTextSelected()) {
-                    Log.e(LOG_TAG, "Selection state is off, but selected");
+                    Log.e(LOG_TAG, "Selection is off, but selected");
                 }
                 setSelectStartPos();
                 mEST.setHintMessage(HINT_MSG_SELECT_END);
             } else if (mState == STATE_SELECT_ON) {
                 if (isTextSelected()) {
-                    Log.e(LOG_TAG, "Selection state now start, but selected");
+                    Log.e(LOG_TAG, "Selection now start, but selected");
                 }
                 setSelectEndPos();
                 mEST.setHintMessage(HINT_MSG_PUSH_COMPETE);
                 doNextHandle();
             } else if (mState == STATE_SELECTED) {
                 if (!isTextSelected()) {
-                    Log.e(LOG_TAG,
-                            "Selection state is done, but not selected");
+                    Log.e(LOG_TAG, "Selection is done, but not selected");
                 }
                 setSelectEndPos();
                 doNextHandle();
@@ -537,6 +681,9 @@
         }
 
         private void doNextHandle() {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- doNextHandle: " + mMode + "," + mState);
+            }
             switch (mMode) {
             case MODE_COPY:
                 handleCopy();
@@ -556,6 +703,9 @@
         }
 
         private void handleResetEdit() {
+            if (DBG) {
+                Log.d(LOG_TAG, "Reset Editor");
+            }
             handleCancel();
             mEditFlag = true;
             mEST.setHintMessage(HINT_MSG_SELECT_START);
@@ -564,7 +714,7 @@
         // Methods of selection
         private void onSelect() {
             if (DBG) {
-                Log.d(LOG_TAG, "--- onSelect");
+                Log.d(LOG_TAG, "--- onSelect:" + mCurStart + "," + mCurEnd);
             }
             if (mCurStart >= 0 && mCurStart <= mEST.getText().length()
                     && mCurEnd >= 0 && mCurEnd <= mEST.getText().length()) {
@@ -650,4 +800,132 @@
         }
     }
 
+    private class StyledTextConverter {
+        private EditStyledText mEST;
+
+        public StyledTextConverter(EditStyledText est) {
+            mEST = est;
+        }
+
+        public String getConvertedBody() {
+            String htmlBody = Html.toHtml(mEST.getText());
+            return htmlBody;
+        }
+    }
+
+    private class StyledTextToast {
+        Builder mBuilder;
+        CharSequence mColorTitle;
+        CharSequence mSizeTitle;
+        CharSequence[] mColorNames;
+        CharSequence[] mColorInts;
+        CharSequence[] mSizeNames;
+        CharSequence[] mSizeDisplayInts;
+        CharSequence[] mSizeSendInts;
+        EditStyledText mEST;
+
+        public StyledTextToast(EditStyledText est) {
+            mEST = est;
+        }
+
+        public void setBuilder(Builder builder) {
+            mBuilder = builder;
+        }
+
+        public void setColorAlertParams(CharSequence colortitle,
+                CharSequence[] colornames, CharSequence[] colorints) {
+            mColorTitle = colortitle;
+            mColorNames = colornames;
+            mColorInts = colorints;
+        }
+
+        public void setSizeAlertParams(CharSequence sizetitle,
+                CharSequence[] sizenames, CharSequence[] sizedisplayints,
+                CharSequence[] sizesendints) {
+            mSizeTitle = sizetitle;
+            mSizeNames = sizenames;
+            mSizeDisplayInts = sizedisplayints;
+            mSizeSendInts = sizesendints;
+        }
+
+        public boolean checkColorAlertParams() {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- checkParams");
+            }
+            if (mBuilder == null) {
+                Log.e(LOG_TAG, "--- builder is null.");
+                return false;
+            } else if (mColorTitle == null || mColorNames == null
+                    || mColorInts == null) {
+                Log.e(LOG_TAG, "--- color alert params are null.");
+                return false;
+            } else if (mColorNames.length != mColorInts.length) {
+                Log.e(LOG_TAG, "--- the length of color alert params are "
+                        + "different.");
+                return false;
+            }
+            return true;
+        }
+
+        public boolean checkSizeAlertParams() {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- checkParams");
+            }
+            if (mBuilder == null) {
+                Log.e(LOG_TAG, "--- builder is null.");
+            } else if (mSizeTitle == null || mSizeNames == null
+                    || mSizeDisplayInts == null || mSizeSendInts == null) {
+                Log.e(LOG_TAG, "--- size alert params are null.");
+            } else if (mSizeNames.length != mSizeDisplayInts.length
+                    && mSizeSendInts.length != mSizeDisplayInts.length) {
+                Log.e(LOG_TAG, "--- the length of size alert params are "
+                        + "different.");
+            }
+            return true;
+        }
+
+        private void onShowColorAlertDialog() {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- onShowAlertDialog");
+            }
+            if (!checkColorAlertParams()) {
+                return;
+            }
+            mBuilder.setTitle(mColorTitle);
+            mBuilder.setIcon(0);
+            mBuilder.
+            setItems(mColorNames,
+                    new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d("EETVM", "mBuilder.onclick:" + which);
+                    int color = Integer.parseInt(
+                            (String) mColorInts[which], 16) - 0x01000000;
+                    mEST.setItemColor(color);
+                }
+            });
+            mBuilder.show();
+        }
+
+        private void onShowSizeAlertDialog() {
+            if (DBG) {
+                Log.d(LOG_TAG, "--- onShowAlertDialog");
+            }
+            if (!checkColorAlertParams()) {
+                return;
+            }
+            mBuilder.setTitle(mSizeTitle);
+            mBuilder.setIcon(0);
+            mBuilder.
+            setItems(mSizeNames,
+                    new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    Log.d("EETVM", "mBuilder.onclick:" + which);
+                    int size = Integer
+                    .parseInt((String) mSizeDisplayInts[which]);
+                    mEST.setItemSize(size);
+                }
+            });
+            mBuilder.show();
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index c8b3ad4..f0b311c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -78,6 +78,7 @@
 
     private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
     private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
+    private final static String PATTERN_EVER_CHOSEN = "lockscreen.patterneverchosen";
 
     private final ContentResolver mContentResolver;
 
@@ -139,6 +140,16 @@
     }
 
     /**
+     * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
+     * currently cleared.
+     *
+     * @return True if the user has ever chosen a pattern.
+     */
+    public boolean isPatternEverChosen() {
+        return getBoolean(PATTERN_EVER_CHOSEN);
+    }
+
+    /**
      * Save a lock pattern.
      * @param pattern The new pattern to save.
      */
@@ -155,6 +166,7 @@
                 raf.write(hash, 0, hash.length);
             }
             raf.close();
+            setBoolean(PATTERN_EVER_CHOSEN, true);
         } catch (FileNotFoundException fnfe) {
             // Cant do much, unless we want to fail over to using the settings provider
             Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
index 1429f58..971f87c 100644
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ b/core/jni/android_os_ParcelFileDescriptor.cpp
@@ -15,6 +15,8 @@
 ** limitations under the License.
 */
 
+//#define LOG_NDEBUG 0
+
 #include "JNIHelp.h"
 
 #include <fcntl.h>
@@ -45,6 +47,11 @@
     jfieldID mFileDescriptor;
 } gSocketImplOffsets;
 
+static struct parcel_file_descriptor_offsets_t
+{
+    jclass mClass;
+    jfieldID mFileDescriptor;
+} gParcelFileDescriptorOffsets;
 
 static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromSocket(JNIEnv* env,
     jobject clazz, jobject object)
@@ -60,10 +67,21 @@
     return fileDescriptorClone;
 }
 
+static jint getFd(JNIEnv* env, jobject clazz)
+{
+    jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
+    if (descriptor == NULL) return -1;
+    return env->GetIntField(descriptor, gFileDescriptorOffsets.mDescriptor);
+}
+
 static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
     jobject clazz)
 {
-    jint fd = env->GetIntField(clazz, gFileDescriptorOffsets.mDescriptor);
+    jint fd = getFd(env, clazz);
+    if (fd < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
+        return -1;
+    }
     
     struct stat st;
     if (fstat(fd, &st) != 0) {
@@ -80,7 +98,12 @@
 static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
     jobject clazz, jlong pos)
 {
-    jint fd = env->GetIntField(clazz, gFileDescriptorOffsets.mDescriptor);
+    jint fd = getFd(env, clazz);
+    if (fd < 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
+        return -1;
+    }
+    
     return lseek(fd, pos, SEEK_SET);
 }
 
@@ -121,6 +144,10 @@
     
     clazz = env->FindClass(kParcelFileDescriptorPathName);
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
+    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
+    gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;");
+    LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL,
+                 "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor");
 
     return AndroidRuntime::registerNativeMethods(
         env, kParcelFileDescriptorPathName,
diff --git a/core/res/res/anim/app_starting_exit.xml b/core/res/res/anim/app_starting_exit.xml
index c6f94b0..0675575 100644
--- a/core/res/res/anim/app_starting_exit.xml
+++ b/core/res/res/anim/app_starting_exit.xml
@@ -19,6 +19,6 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
 
diff --git a/core/res/res/anim/dialog_enter.xml b/core/res/res/anim/dialog_enter.xml
index f48dd37..cc409e8 100644
--- a/core/res/res/anim/dialog_enter.xml
+++ b/core/res/res/anim/dialog_enter.xml
@@ -23,7 +23,7 @@
     <scale android:fromXScale="0.9" android:toXScale="1.0"
            android:fromYScale="0.9" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
-           android:duration="75" />
+           android:duration="@android:integer/config_shortAnimTime" />
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:duration="75" />
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/dialog_exit.xml b/core/res/res/anim/dialog_exit.xml
index 24de6e7..8bf8082 100644
--- a/core/res/res/anim/dialog_exit.xml
+++ b/core/res/res/anim/dialog_exit.xml
@@ -22,7 +22,7 @@
     <scale android:fromXScale="1.0" android:toXScale="0.9"
            android:fromYScale="1.0" android:toYScale="0.9"
            android:pivotX="50%" android:pivotY="50%"
-           android:duration="75" />
+           android:duration="@android:integer/config_shortAnimTime" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:duration="75"/>
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/fade_in.xml b/core/res/res/anim/fade_in.xml
index 32eea01..57310d9 100644
--- a/core/res/res/anim/fade_in.xml
+++ b/core/res/res/anim/fade_in.xml
@@ -18,4 +18,7 @@
 */
 -->
 
-<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_longAnimTime" />
diff --git a/core/res/res/anim/fade_out.xml b/core/res/res/anim/fade_out.xml
index e8ae9c1..dc76276 100644
--- a/core/res/res/anim/fade_out.xml
+++ b/core/res/res/anim/fade_out.xml
@@ -21,5 +21,5 @@
 <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" 
     android:fromAlpha="1.0"
     android:toAlpha="0.0"
-    android:duration="300" 
+    android:duration="@android:integer/config_mediumAnimTime" 
 />
diff --git a/core/res/res/anim/grow_fade_in.xml b/core/res/res/anim/grow_fade_in.xml
index 0969857..5dc41cb 100644
--- a/core/res/res/anim/grow_fade_in.xml
+++ b/core/res/res/anim/grow_fade_in.xml
@@ -21,6 +21,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
            android:fromYScale="0.3" android:toYScale="1.0"
-           android:pivotX="0%" android:pivotY="0%" android:duration="125" />
-    <alpha android:interpolator="@anim/decelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+           android:pivotX="0%" android:pivotY="0%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/decelerate_interpolator"
+            android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/grow_fade_in_center.xml b/core/res/res/anim/grow_fade_in_center.xml
index 01d7a77..c07a82e 100644
--- a/core/res/res/anim/grow_fade_in_center.xml
+++ b/core/res/res/anim/grow_fade_in_center.xml
@@ -21,6 +21,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="0.6" android:toXScale="1.0"
            android:fromYScale="0.6" android:toYScale="1.0"
-           android:pivotX="50%" android:pivotY="50%" android:duration="125" />
-    <alpha android:interpolator="@anim/decelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+           android:pivotX="50%" android:pivotY="50%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/decelerate_interpolator"
+            android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/grow_fade_in_from_bottom.xml b/core/res/res/anim/grow_fade_in_from_bottom.xml
index d3e468d..848c677 100644
--- a/core/res/res/anim/grow_fade_in_from_bottom.xml
+++ b/core/res/res/anim/grow_fade_in_from_bottom.xml
@@ -21,6 +21,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="0.5" android:toXScale="1.0"
            android:fromYScale="0.5" android:toYScale="1.0"
-           android:pivotX="0%" android:pivotY="100%" android:duration="125" />
-    <alpha android:interpolator="@anim/decelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+           android:pivotX="0%" android:pivotY="100%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/decelerate_interpolator"
+            android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/input_method_enter.xml b/core/res/res/anim/input_method_enter.xml
index 6263c37649..3858651 100644
--- a/core/res/res/anim/input_method_enter.xml
+++ b/core/res/res/anim/input_method_enter.xml
@@ -20,7 +20,8 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator">
-    <translate android:fromYDelta="20%" android:toYDelta="0" android:duration="100"/>
+    <translate android:fromYDelta="20%" android:toYDelta="0"
+            android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
-            android:duration="100" />
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/input_method_exit.xml b/core/res/res/anim/input_method_exit.xml
index af9382c..25369ab 100644
--- a/core/res/res/anim/input_method_exit.xml
+++ b/core/res/res/anim/input_method_exit.xml
@@ -19,7 +19,8 @@
 -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/accelerate_interpolator">
-    <translate android:fromYDelta="0" android:toYDelta="20%" android:duration="100"/>
+    <translate android:fromYDelta="0" android:toYDelta="20%"
+            android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:duration="100"/>
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/input_method_fancy_enter.xml b/core/res/res/anim/input_method_fancy_enter.xml
index 15f5ad7..c6949b3 100644
--- a/core/res/res/anim/input_method_fancy_enter.xml
+++ b/core/res/res/anim/input_method_fancy_enter.xml
@@ -23,6 +23,7 @@
     <scale android:fromXScale="2.0" android:toXScale="1.0"
            android:fromYScale="2.0" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
-           android:duration="100" />
-    <translate android:fromYDelta="100%" android:toYDelta="0" android:duration="100"/>
+           android:duration="@android:integer/config_shortAnimTime" />
+    <translate android:fromYDelta="100%" android:toYDelta="0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/input_method_fancy_exit.xml b/core/res/res/anim/input_method_fancy_exit.xml
index ecc5de3..7333cca 100644
--- a/core/res/res/anim/input_method_fancy_exit.xml
+++ b/core/res/res/anim/input_method_fancy_exit.xml
@@ -22,6 +22,7 @@
     <scale android:fromXScale="1.0" android:toXScale="2.0"
            android:fromYScale="1.0" android:toYScale="2.0"
            android:pivotX="50%" android:pivotY="50%"
-           android:duration="100" />
-    <translate android:fromYDelta="0" android:toYDelta="100%" android:duration="100"/>
+           android:duration="@android:integer/config_shortAnimTime" />
+    <translate android:fromYDelta="0" android:toYDelta="100%"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/lock_screen_exit.xml b/core/res/res/anim/lock_screen_exit.xml
index 54d8e93..55c5ec9 100644
--- a/core/res/res/anim/lock_screen_exit.xml
+++ b/core/res/res/anim/lock_screen_exit.xml
@@ -19,5 +19,6 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/options_panel_enter.xml b/core/res/res/anim/options_panel_enter.xml
index 9614014..d81866b 100644
--- a/core/res/res/anim/options_panel_enter.xml
+++ b/core/res/res/anim/options_panel_enter.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromYDelta="25%" android:toYDelta="0" android:duration="75"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+	<translate android:fromYDelta="25%" android:toYDelta="0"
+        android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/options_panel_exit.xml b/core/res/res/anim/options_panel_exit.xml
index c9bee1d..4e7af7a 100644
--- a/core/res/res/anim/options_panel_exit.xml
+++ b/core/res/res/anim/options_panel_exit.xml
@@ -19,7 +19,9 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
-	<translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
+	<translate android:fromYDelta="0" android:toYDelta="50%"
+            android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
 
diff --git a/core/res/res/anim/push_down_in.xml b/core/res/res/anim/push_down_in.xml
index 1cb1597..6ab9a04 100644
--- a/core/res/res/anim/push_down_in.xml
+++ b/core/res/res/anim/push_down_in.xml
@@ -15,6 +15,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="-100%p" android:toYDelta="0" android:duration="300"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
+	<translate android:fromYDelta="-100%p" android:toYDelta="0"
+            android:duration="@android:integer/config_longAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_longAnimTime" />
 </set>
diff --git a/core/res/res/anim/push_down_out.xml b/core/res/res/anim/push_down_out.xml
index 1ad49b0..ce36458 100644
--- a/core/res/res/anim/push_down_out.xml
+++ b/core/res/res/anim/push_down_out.xml
@@ -15,6 +15,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="0" android:toYDelta="100%p" android:duration="300"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" />
+	<translate android:fromYDelta="0" android:toYDelta="100%p"
+            android:duration="@android:integer/config_longAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_longAnimTime" />
 </set>
diff --git a/core/res/res/anim/push_up_in.xml b/core/res/res/anim/push_up_in.xml
index a2f47e9..6ef582c 100644
--- a/core/res/res/anim/push_up_in.xml
+++ b/core/res/res/anim/push_up_in.xml
@@ -15,6 +15,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="100%p" android:toYDelta="0" android:duration="300"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300" />
+	<translate android:fromYDelta="100%p" android:toYDelta="0"
+            android:duration="@android:integer/config_longAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_longAnimTime" />
 </set>
diff --git a/core/res/res/anim/push_up_out.xml b/core/res/res/anim/push_up_out.xml
index 2803435..2b267d5 100644
--- a/core/res/res/anim/push_up_out.xml
+++ b/core/res/res/anim/push_up_out.xml
@@ -15,6 +15,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="0" android:toYDelta="-100%p" android:duration="300"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300" />
+	<translate android:fromYDelta="0" android:toYDelta="-100%p"
+            android:duration="@android:integer/config_longAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_longAnimTime" />
 </set>
diff --git a/core/res/res/anim/search_bar_enter.xml b/core/res/res/anim/search_bar_enter.xml
index ecb86c1..c85caaa 100644
--- a/core/res/res/anim/search_bar_enter.xml
+++ b/core/res/res/anim/search_bar_enter.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromYDelta="-25%" android:toYDelta="0" android:duration="75"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+	<translate android:fromYDelta="-25%" android:toYDelta="0"
+            android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/search_bar_exit.xml b/core/res/res/anim/search_bar_exit.xml
index db7142e..1609a12 100644
--- a/core/res/res/anim/search_bar_exit.xml
+++ b/core/res/res/anim/search_bar_exit.xml
@@ -19,7 +19,9 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
-	<translate android:fromYDelta="0" android:toYDelta="-50%" android:duration="50"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
+	<translate android:fromYDelta="0" android:toYDelta="-50%"
+            android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
 
diff --git a/core/res/res/anim/shrink_fade_out.xml b/core/res/res/anim/shrink_fade_out.xml
index ae15ff9..4000c23 100644
--- a/core/res/res/anim/shrink_fade_out.xml
+++ b/core/res/res/anim/shrink_fade_out.xml
@@ -20,6 +20,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
            android:fromYScale="1.0" android:toYScale="0.3"
-           android:pivotX="0%" android:pivotY="0%" android:duration="125" />
-    <alpha android:interpolator="@anim/accelerate_interpolator" android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="75"/>
+           android:pivotX="0%" android:pivotY="0%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/accelerate_interpolator"
+            android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/shrink_fade_out_center.xml b/core/res/res/anim/shrink_fade_out_center.xml
index 7b0be34..a41731e 100644
--- a/core/res/res/anim/shrink_fade_out_center.xml
+++ b/core/res/res/anim/shrink_fade_out_center.xml
@@ -20,6 +20,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="1.0" android:toXScale="0.5"
            android:fromYScale="1.0" android:toYScale="0.5"
-           android:pivotX="50%" android:pivotY="50%" android:duration="125" />
-    <alpha android:interpolator="@anim/accelerate_interpolator" android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="75"/>
+           android:pivotX="50%" android:pivotY="50%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/accelerate_interpolator"
+            android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/shrink_fade_out_from_bottom.xml b/core/res/res/anim/shrink_fade_out_from_bottom.xml
index 61f29d5..345a2e061 100644
--- a/core/res/res/anim/shrink_fade_out_from_bottom.xml
+++ b/core/res/res/anim/shrink_fade_out_from_bottom.xml
@@ -20,6 +20,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
            android:fromYScale="1.0" android:toYScale="0.3"
-           android:pivotX="0%" android:pivotY="100%" android:duration="125" />
-    <alpha android:interpolator="@anim/accelerate_interpolator" android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="75"/>
+           android:pivotX="0%" android:pivotY="100%"
+           android:duration="@android:integer/config_shortAnimTime" />
+    <alpha android:interpolator="@anim/accelerate_interpolator"
+            android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/slide_in_bottom.xml b/core/res/res/anim/slide_in_bottom.xml
index 569d974..d111854 100644
--- a/core/res/res/anim/slide_in_bottom.xml
+++ b/core/res/res/anim/slide_in_bottom.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="50%p" android:toYDelta="0" android:duration="200"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
+	<translate android:fromYDelta="50%p" android:toYDelta="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_in_child_bottom.xml b/core/res/res/anim/slide_in_child_bottom.xml
index ce51c36..2ab0f66 100644
--- a/core/res/res/anim/slide_in_child_bottom.xml
+++ b/core/res/res/anim/slide_in_child_bottom.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromYDelta="100%" android:toYDelta="0" android:duration="200"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
+	<translate android:fromYDelta="100%" android:toYDelta="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_in_left.xml b/core/res/res/anim/slide_in_left.xml
index 033bfe2..9a585f5 100644
--- a/core/res/res/anim/slide_in_left.xml
+++ b/core/res/res/anim/slide_in_left.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromXDelta="-50%p" android:toXDelta="0" android:duration="200"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
+	<translate android:fromXDelta="-50%p" android:toXDelta="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_in_right.xml b/core/res/res/anim/slide_in_right.xml
index 76b336c..125060e 100644
--- a/core/res/res/anim/slide_in_right.xml
+++ b/core/res/res/anim/slide_in_right.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromXDelta="50%p" android:toXDelta="0" android:duration="200"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
+	<translate android:fromXDelta="50%p" android:toXDelta="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_in_top.xml b/core/res/res/anim/slide_in_top.xml
index 15df913..f4810ab 100644
--- a/core/res/res/anim/slide_in_top.xml
+++ b/core/res/res/anim/slide_in_top.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="-50%p" android:toYDelta="0" android:duration="200"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="200" />
+	<translate android:fromYDelta="-50%p" android:toYDelta="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_out_bottom.xml b/core/res/res/anim/slide_out_bottom.xml
index 8f6e8b0..8ddcd59 100644
--- a/core/res/res/anim/slide_out_bottom.xml
+++ b/core/res/res/anim/slide_out_bottom.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="0" android:toYDelta="50%p" android:duration="200"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<translate android:fromYDelta="0" android:toYDelta="50%p"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_out_left.xml b/core/res/res/anim/slide_out_left.xml
index 979d10a..73337d4 100644
--- a/core/res/res/anim/slide_out_left.xml
+++ b/core/res/res/anim/slide_out_left.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromXDelta="0" android:toXDelta="-50%p" android:duration="200"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<translate android:fromXDelta="0" android:toXDelta="-50%p"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_out_right.xml b/core/res/res/anim/slide_out_right.xml
index b5f9bb9..de8c512 100644
--- a/core/res/res/anim/slide_out_right.xml
+++ b/core/res/res/anim/slide_out_right.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromXDelta="0" android:toXDelta="50%p" android:duration="200"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<translate android:fromXDelta="0" android:toXDelta="50%p"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/slide_out_top.xml b/core/res/res/anim/slide_out_top.xml
index b15323e..3134a57 100644
--- a/core/res/res/anim/slide_out_top.xml
+++ b/core/res/res/anim/slide_out_top.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromYDelta="0" android:toYDelta="-50%p" android:duration="200"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" />
+	<translate android:fromYDelta="0" android:toYDelta="-50%p"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/status_bar_enter.xml b/core/res/res/anim/status_bar_enter.xml
index b57d8e7..d308ad5 100644
--- a/core/res/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/status_bar_enter.xml
@@ -20,7 +20,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
 	<translate android:fromYDelta="-75%" android:toYDelta="0"
-        android:duration="200"/>
+        android:duration="@android:integer/config_mediumAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:duration="200" />
+        android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/status_bar_exit.xml b/core/res/res/anim/status_bar_exit.xml
index 8c6dc1c..43a1b9a 100644
--- a/core/res/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/status_bar_exit.xml
@@ -20,7 +20,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
 	<translate android:fromYDelta="0" android:toYDelta="-75%"
-        android:startOffset="100" android:duration="200"/>
+        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-        android:startOffset="100" android:duration="200" />
+        android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/submenu_enter.xml b/core/res/res/anim/submenu_enter.xml
index 32a8054..5a94971 100644
--- a/core/res/res/anim/submenu_enter.xml
+++ b/core/res/res/anim/submenu_enter.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromXDelta="-25%" android:toXDelta="0" android:duration="100"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="100" />
+	<translate android:fromXDelta="-25%" android:toXDelta="0"
+            android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/submenu_exit.xml b/core/res/res/anim/submenu_exit.xml
index 9283751..20fbefc 100644
--- a/core/res/res/anim/submenu_exit.xml
+++ b/core/res/res/anim/submenu_exit.xml
@@ -19,6 +19,8 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android">
-	<translate android:fromXDelta="0" android:toXDelta="25%" android:duration="50"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
+	<translate android:fromXDelta="0" android:toXDelta="25%"
+            android:duration="@android:integer/config_shortAnimTime"/>
+	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index 6bef7a4..c289869 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -21,5 +21,6 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
-	<translate android:fromXDelta="-100%" android:toXDelta="0" android:duration="200"/>
+	<translate android:fromXDelta="-100%" android:toXDelta="0"
+        android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index 48dc31a..96fff94 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -20,5 +20,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromXDelta="0%" android:toXDelta="33%" android:duration="200"/>
+	<translate android:fromXDelta="0%" android:toXDelta="33%"
+        android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index e498c9d..8e7d049 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -20,5 +20,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator">
-	<translate android:fromXDelta="33%" android:toXDelta="0" android:duration="200"/>
+	<translate android:fromXDelta="33%" android:toXDelta="0"
+        android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 8ef4006..5e5c66d 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -21,5 +21,6 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
-	<translate android:fromXDelta="0%" android:toXDelta="-100%" android:duration="200"/>
+	<translate android:fromXDelta="0%" android:toXDelta="-100%"
+        android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
diff --git a/core/res/res/anim/toast_enter.xml b/core/res/res/anim/toast_enter.xml
index 83cb1fe..57310d9 100644
--- a/core/res/res/anim/toast_enter.xml
+++ b/core/res/res/anim/toast_enter.xml
@@ -20,4 +20,5 @@
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
-        android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="400" />
+        android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_longAnimTime" />
diff --git a/core/res/res/anim/toast_exit.xml b/core/res/res/anim/toast_exit.xml
index f922085..b7c5fa0 100644
--- a/core/res/res/anim/toast_exit.xml
+++ b/core/res/res/anim/toast_exit.xml
@@ -20,5 +20,6 @@
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/accelerate_interpolator" 
-        android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="400" 
+        android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:duration="@android:integer/config_longAnimTime" 
 />
diff --git a/core/res/res/drawable-land/statusbar_background.png b/core/res/res/drawable-land/statusbar_background.png
index bafa5c5..2a351a5 100644
--- a/core/res/res/drawable-land/statusbar_background.png
+++ b/core/res/res/drawable-land/statusbar_background.png
Binary files differ
diff --git a/core/res/res/drawable/scrollbar_handle_horizontal.9.png b/core/res/res/drawable/scrollbar_handle_horizontal.9.png
index 324b4bd..8584d1f 100755
--- a/core/res/res/drawable/scrollbar_handle_horizontal.9.png
+++ b/core/res/res/drawable/scrollbar_handle_horizontal.9.png
Binary files differ
diff --git a/core/res/res/drawable/scrollbar_handle_vertical.9.png b/core/res/res/drawable/scrollbar_handle_vertical.9.png
index 3519d68..331a05d 100755
--- a/core/res/res/drawable/scrollbar_handle_vertical.9.png
+++ b/core/res/res/drawable/scrollbar_handle_vertical.9.png
Binary files differ
diff --git a/core/res/res/drawable/statusbar_background.png b/core/res/res/drawable/statusbar_background.png
index 25a2344..2d8aa7a 100644
--- a/core/res/res/drawable/statusbar_background.png
+++ b/core/res/res/drawable/statusbar_background.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 19305c5..881652b 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -20,7 +20,7 @@
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:background="#A0000000"
+    android:background="@android:color/background_dark"
         >
 
     <!-- displays dots as user enters pin -->
@@ -49,7 +49,6 @@
             />
 
         <ImageButton android:id="@+id/backspace"
-             style="@android:style/Widget.Button.Inset"
              android:src="@android:drawable/ic_input_delete"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
index 6a05488..fc82e3f 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -16,231 +16,251 @@
 ** limitations under the License.
 */
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:background="#A0000000"
+    android:background="@android:color/background_dark"
         >
 
-    <!-- header text ('Enter Pin Code') -->
-    <TextView android:id="@+id/headerText"
+    <LinearLayout android:id="@+id/topDisplayGroup"
         android:layout_width="fill_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-        android:gravity="center"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:textSize="26sp"
-            />
+        android:layout_height="115dip"
+        android:layout_alignParentTop="true"
+        android:orientation="vertical"
+            >
 
-    <!-- displays dots as user enters pin -->
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:addStatesFromChildren="true"
-        android:gravity="center_vertical"
-        android:baselineAligned="false"
-        android:paddingRight="0dip"
-        android:layout_marginTop="8dip"
-        android:layout_marginBottom="5dip"
-        android:layout_marginLeft="5dip"
-        android:background="@android:drawable/edit_text"
-    >
+        <!-- header text ('Enter Pin Code') -->
+        <TextView android:id="@+id/headerText"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="9dip"
+            android:gravity="center"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+                />
 
-        <EditText android:id="@+id/pinDisplay"
-            android:layout_width="0dip"
-            android:layout_weight="1"
-            android:layout_height="fill_parent"
-            android:maxLines="1"
-            android:background="@null"
-            android:inputType="textPassword"
-            />
+        <RelativeLayout
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="18dip"
+            android:layout_marginRight="6dip"
+            android:layout_marginLeft="6dip"
+            android:background="@android:drawable/edit_text"
+            >
 
-        <ImageButton android:id="@+id/backspace"
-             style="@android:style/Widget.Button.Inset"
-             android:src="@android:drawable/ic_input_delete"
-             android:layout_width="wrap_content"
-             android:layout_height="fill_parent"
-             android:layout_marginTop="2dip"
-             android:layout_marginRight="2dip"
-             android:layout_marginBottom="2dip"
-             android:gravity="center"
-            />
+            <!-- displays dots as user enters pin -->
+            <TextView android:id="@+id/pinDisplay"
+                android:layout_width="wrap_content"
+                android:layout_height="64dip"
+                android:layout_centerInParent="true"
+                android:maxLines="1"
+                android:textAppearance="?android:attr/textAppearanceLargeInverse"
+                android:textStyle="bold"
+                android:inputType="textPassword"
+                />
+
+            <ImageButton android:id="@+id/backspace"
+                android:src="@android:drawable/ic_input_delete"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_centerVertical="true"
+                android:layout_marginRight="1dip"
+                    />
+        </RelativeLayout>
+
 
     </LinearLayout>
 
     <!-- Keypad section -->
-    <LinearLayout
+    <LinearLayout android:id="@+id/keyPad"
         android:layout_width="fill_parent"
-        android:layout_height="0sp"
-        android:layout_weight="1"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="4dip"
-        android:orientation="horizontal"
-    >
+        android:layout_height="wrap_content"
+        android:layout_below="@id/topDisplayGroup"
+        android:orientation="vertical"
+        >
 
-        <Button android:id="@+id/one"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="64dip"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip"
+            android:orientation="horizontal"
+        >
 
-        <Button android:id="@+id/two"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+            <Button android:id="@+id/one"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-        <Button android:id="@+id/three"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
-    </LinearLayout>
+            <Button android:id="@+id/two"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-    <LinearLayout
-        android:layout_width="fill_parent"
-        android:layout_height="0sp"
-        android:layout_weight="1"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="4dip"
-        android:orientation="horizontal"
-    >
+            <Button android:id="@+id/three"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
+        </LinearLayout>
 
-        <Button android:id="@+id/four"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="64dip"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip"
+            android:orientation="horizontal"
+        >
 
-        <Button android:id="@+id/five"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+            <Button android:id="@+id/four"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-        <Button android:id="@+id/six"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
-    </LinearLayout>
+            <Button android:id="@+id/five"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-    <LinearLayout
-        android:layout_width="fill_parent"
-        android:layout_height="0sp"
-        android:layout_weight="1"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="4dip"
-        android:orientation="horizontal"
-    >
+            <Button android:id="@+id/six"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
+        </LinearLayout>
 
-        <Button android:id="@+id/seven"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="64dip"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip"
+            android:orientation="horizontal"
+        >
 
-        <Button android:id="@+id/eight"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+            <Button android:id="@+id/seven"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-        <Button android:id="@+id/nine"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
-    </LinearLayout>
+            <Button android:id="@+id/eight"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
 
-    <LinearLayout
-        android:layout_width="fill_parent"
-        android:layout_height="0sp"
-        android:layout_weight="1"
-        android:layout_marginLeft="5dip"
-        android:layout_marginRight="4dip"
-        android:orientation="horizontal"
-    >
+            <Button android:id="@+id/nine"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
+        </LinearLayout>
 
-        <Button android:id="@+id/ok"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="18sp"
-            android:text="@android:string/ok"
-        />
+        <LinearLayout
+            android:layout_width="fill_parent"
+            android:layout_height="64dip"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip"
+            android:orientation="horizontal"
+        >
 
-        <Button android:id="@+id/zero"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="22sp"
-        />
+            <Button android:id="@+id/ok"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textStyle="bold"
+                android:text="@android:string/ok"
+            />
 
-        <Button android:id="@+id/cancel"
-            android:layout_width="0sp"
-            android:layout_height="fill_parent"
-            android:layout_weight="1"
-            android:paddingLeft="4dip"
-            style="?android:attr/buttonStyleSmall"
-            android:textSize="18sp"
-            android:text="@android:string/cancel"
-        />
+            <Button android:id="@+id/zero"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textStyle="bold"
+            />
+
+            <Button android:id="@+id/cancel"
+                android:layout_width="0sp"
+                android:layout_height="fill_parent"
+                android:layout_weight="1"
+                android:layout_marginLeft="2dip"
+                android:layout_marginRight="2dip"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textStyle="bold"
+                android:text="@android:string/cancel"
+            />
+        </LinearLayout>
+
+    <!-- end keypad -->
     </LinearLayout>
 
 
     <!-- emergency call button -->
-    <RelativeLayout
+    <Button
+        android:id="@+id/emergencyCall"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_alignParentBottom="true"
+        android:drawableLeft="@android:drawable/ic_emergency"
+        android:drawablePadding="3dip"
+        android:text="@android:string/lockscreen_emergency_call"
+        />
+
+    <!-- spacer below keypad -->
+    <View
+        android:id="@+id/spacerBottom"
         android:layout_width="fill_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-        >
+        android:layout_height="1dip"
+        android:layout_marginBottom="6dip"
+        android:layout_above="@id/emergencyCall"
+        android:background="@android:drawable/divider_horizontal_dark"/>
 
-        <Button
-            android:id="@+id/emergencyCall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_centerInParent="true"
-            android:drawableLeft="@drawable/ic_emergency"
-            android:drawablePadding="3dip"
-            android:paddingTop="4dip"
-            android:paddingBottom="4dip"
-            android:text="@android:string/lockscreen_emergency_call"
-            />
 
-    </RelativeLayout>
-
-</LinearLayout>
+</RelativeLayout>
diff --git a/core/res/res/layout/select_dialog_singlechoice.xml b/core/res/res/layout/select_dialog_singlechoice.xml
index ec97d7b..3e07f23 100644
--- a/core/res/res/layout/select_dialog_singlechoice.xml
+++ b/core/res/res/layout/select_dialog_singlechoice.xml
@@ -19,7 +19,8 @@
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    android:textAppearance="?android:attr/textAppearanceLarge"
+    android:textColor="@android:color/bright_foreground_light"
     android:gravity="center_vertical"
     android:paddingLeft="12dip"
     android:paddingRight="7dip"
diff --git a/core/res/res/layout/zoom_container.xml b/core/res/res/layout/zoom_container.xml
index fc5cf3d..52bc635 100644
--- a/core/res/res/layout/zoom_container.xml
+++ b/core/res/res/layout/zoom_container.xml
@@ -19,10 +19,11 @@
 -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     <ZoomControls android:id="@+id/zoomControls"
-        android:layout_gravity="bottom|center_horizontal"
+        android:layout_gravity="center_horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         style="@style/ZoomControls"
+        android:gravity="center_horizontal"
         android:background="@null"
         />
 </merge>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 3fb7e86..8150067 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -19,7 +19,7 @@
 -->
 <resources>
 	<drawable name="screen_background_light">#ffffffff</drawable>
-	<drawable name="screen_background_dark">#ff262626</drawable>
+	<drawable name="screen_background_dark">#ff1a1a1a</drawable>
     <drawable name="status_bar_closed_default_background">#ff000000</drawable>
     <drawable name="status_bar_opened_default_background">#ff000000</drawable>
     <drawable name="search_bar_default_color">#ff000000</drawable>
@@ -28,7 +28,7 @@
     <color name="white">#ffffffff</color>
     <color name="black">#ff000000</color>
     <color name="transparent">#00000000</color>
-    <color name="background_dark">#ff262626</color>
+    <color name="background_dark">#ff1a1a1a</color>
     <color name="bright_foreground_dark">#ffffffff</color>
     <color name="bright_foreground_dark_disabled">#80ffffff</color>
     <color name="bright_foreground_dark_inverse">#ff000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f370151..83ac8e2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -25,4 +25,13 @@
          manager will disable alpha trasformation in animations where not
          strictly needed. -->
     <bool name="config_sf_limitedAlpha">false</bool>
+    
+    <!-- The duration (in milliseconds) of a short animation. -->
+    <integer name="config_shortAnimTime">100</integer>
+    
+    <!-- The duration (in milliseconds) of a medium-length animation. -->
+    <integer name="config_mediumAnimTime">150</integer>
+    
+    <!-- The duration (in milliseconds) of a long animation. -->
+    <integer name="config_longAnimTime">300</integer>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0603fa3..88c7b35 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1095,4 +1095,8 @@
 
   <!--  Drawable to use as a background for a taller version of the titlebar -->
   <public type="drawable" name="title_bar_tall" id="0x010800b7" />
+  
+  <public type="integer" name="config_shortAnimTime" id="0x010e0000" />
+  <public type="integer" name="config_mediumAnimTime" id="0x010e0001" />
+  <public type="integer" name="config_longAnimTime" id="0x010e0002" />
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index ff8f8c2..a152410 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -176,7 +176,7 @@
         <item name="android:focusable">true</item>
         <item name="android:clickable">true</item>
         <item name="android:textAppearance">?android:attr/textAppearanceSmallInverse</item>
-        <item name="android:textColor">@android:color/primary_text_light_nodisable</item>
+        <item name="android:textColor">@android:color/primary_text_light</item>
         <item name="android:gravity">center_vertical|center_horizontal</item>
     </style>
 
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index eace996..64d3a40 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -42,6 +42,7 @@
     virtual	status_t		setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual	status_t		setVideoSize(int width, int height) = 0;
     virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
+    virtual     status_t                setParameters(const String8& params) = 0;
     virtual     status_t                setListener(const sp<IMediaPlayerClient>& listener) = 0;
     virtual	status_t		prepare() = 0;
     virtual	status_t		getMaxAmplitude(int* max) = 0;
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index 3315c59..0c71932 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -45,6 +45,7 @@
     status_t setPreviewSurface(const sp<ISurface>& surface);
     status_t setOutputFile(const char *path);
     status_t setOutputFile(int fd, int64_t offset, int64_t length);
+    status_t setParameters(const String8& params);
     status_t setListener(const sp<IMediaPlayerClient>& listener);
     status_t prepare();
     status_t start();
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 8991f08..78d7621 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -89,14 +89,24 @@
 };
 
 // The "msg" code passed to the listener in notify.
-enum {
-    MEDIA_RECORDER_EVENT_ERROR                    = 1
+enum media_recorder_event_type {
+    MEDIA_RECORDER_EVENT_ERROR                    = 1,
+    MEDIA_RECORDER_EVENT_INFO                     = 2
 };
 
-enum {
+enum media_recorder_error_type {
     MEDIA_RECORDER_ERROR_UNKNOWN                  = 1
 };
 
+// The codes are distributed as follow:
+//   0xx: Reserved
+//   8xx: General info/warning
+// 
+enum media_recorder_info_type {
+    MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
+    MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800
+};
+
 // ----------------------------------------------------------------------------
 // ref-counted object for callbacks
 class MediaRecorderListener: virtual public RefBase
@@ -123,6 +133,7 @@
     status_t    setOutputFile(int fd, int64_t offset, int64_t length);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
+    status_t    setParameters(const String8& params);
     status_t    setListener(const sp<MediaRecorderListener>& listener);
     status_t    prepare();
     status_t    getMaxAmplitude(int* max);
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 57a53bd..5652b28 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -837,12 +837,12 @@
 }
 
 #ifdef WITH_A2DP
-void AudioFlinger::handleStreamDisablesA2dp(int command)
+// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::handleStreamDisablesA2dp_l(int command)
 {
     switch(command) {
     case ACTIVE_TRACK_ADDED:
         {
-            AutoMutex lock(mHardwareLock);
             if (mA2dpDisableCount++ == 0) {
                 if (mA2dpEnabled) {
                     setA2dpEnabled_l(false);
@@ -854,8 +854,7 @@
         break;
     case ACTIVE_TRACK_REMOVED:
         {
-            AutoMutex lock(mHardwareLock);
-            if (mA2dpDisableCount > 0){
+            if (mA2dpDisableCount > 0) {
                 if (--mA2dpDisableCount == 0) {
                     if (mA2dpSuppressed) {
                         setA2dpEnabled_l(true);
@@ -1502,8 +1501,10 @@
             mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
         }        
 #ifdef WITH_A2DP
+        // AudioFlinger::mLock must be locked before calling
+        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
         if (streamDisablesA2dp(track->type())) {
-            mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_ADDED);
+            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
         }
 #endif
     }
@@ -1524,8 +1525,10 @@
             mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
         }
 #ifdef WITH_A2DP
+        // AudioFlinger::mLock must be locked before calling
+        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
         if (streamDisablesA2dp(track->type())) {
-            mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_REMOVED);
+            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
         }
 #endif
     }
@@ -2476,8 +2479,15 @@
     mRecordTrack = recordTrack;
 
 #ifdef WITH_A2DP
-    if (streamDisablesA2dp(recordTrack->type())) {
-        mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_ADDED);
+    { // scope for lock2
+
+        // AudioFlinger::mLock must be locked before calling
+        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
+        AutoMutex lock2(&mAudioFlinger->mLock);
+
+        // Currently there is no way to detect if we are recording over SCO,
+        // so we disable A2DP during any recording.
+        mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
     }
 #endif
 
@@ -2494,8 +2504,15 @@
     AutoMutex lock(&mLock);
     if (mActive && (recordTrack == mRecordTrack.get())) {
 #ifdef WITH_A2DP
-        if (streamDisablesA2dp(recordTrack->type())) {
-            mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_REMOVED);
+        { // scope for lock2
+    
+            // AudioFlinger::mLock must be locked before calling
+            // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
+            AutoMutex lock2(&mAudioFlinger->mLock);
+
+            // Currently there is no way to detect if we are recording over SCO,
+            // so we disable A2DP during any recording.
+            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
         }
 #endif
         mActive = false;
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 596e7f3..ab15947f 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -176,7 +176,7 @@
     };
     void                    handleForcedSpeakerRoute(int command);
 #ifdef WITH_A2DP
-    void                    handleStreamDisablesA2dp(int command);
+    void                    handleStreamDisablesA2dp_l(int command);
 #endif
 
     // Internal dump utilites.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4906cbb..1c08cba 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -71,6 +71,7 @@
     private FileDescriptor mFd;
     private EventHandler mEventHandler;
     private OnErrorListener mOnErrorListener;
+    private OnInfoListener mOnInfoListener;
 
     /**
      * Default constructor.
@@ -256,6 +257,15 @@
     public native void setVideoFrameRate(int rate) throws IllegalStateException;
 
     /**
+     * Sets the maximum duration (in ms) of the recording session.
+     * Call this after setOutFormat() but before prepare().
+     *
+     * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
+     *
+     */
+    public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
+
+    /**
      * Sets the audio encoder to be used for recording. If this method is not
      * called, the output file will not contain an audio track. Call this after
      * setOutputFormat() but before prepare().
@@ -420,6 +430,48 @@
         mOnErrorListener = l;
     }
 
+    /* Do not change these values without updating their counterparts
+     * in include/media/mediarecorder.h!
+     */
+    /** Unspecified media recorder error.
+     * @see android.media.MediaRecorder.OnInfoListener
+     */
+    public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
+    /** A maximum duration had been setup and has now been reached.
+     * @see android.media.MediaRecorder.OnInfoListener
+     */
+    public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
+
+    /**
+     * Interface definition for a callback to be invoked when an error
+     * occurs while recording.
+     */
+    public interface OnInfoListener
+    {
+        /**
+         * Called when an error occurs while recording.
+         * 
+         * @param mr the MediaRecorder that encountered the error
+         * @param what    the type of error that has occurred:
+         * <ul>
+         * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
+         * </ul>
+         * @param extra   an extra code, specific to the error type
+         */
+        void onInfo(MediaRecorder mr, int what, int extra);
+    }
+
+    /**
+     * Register a callback to be invoked when an informational event occurs while
+     * recording.
+     *
+     * @param listener the callback that will be run
+     */
+    public void setOnInfoListener(OnInfoListener listener)
+    {
+        mOnInfoListener = listener;
+    }
+
     private class EventHandler extends Handler
     {
         private MediaRecorder mMediaRecorder;
@@ -429,10 +481,11 @@
             mMediaRecorder = mr;
         }
 
-        /* Do not change this value without updating its counterpart
+        /* Do not change these values without updating their counterparts
          * in include/media/mediarecorder.h!
          */
         private static final int MEDIA_RECORDER_EVENT_ERROR = 1;
+        private static final int MEDIA_RECORDER_EVENT_INFO  = 2;
 
         @Override
         public void handleMessage(Message msg) {
@@ -447,6 +500,12 @@
 
                 return;
 
+            case MEDIA_RECORDER_EVENT_INFO:
+                if (mOnInfoListener != null)
+                    mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
+
+                return;
+
             default:
                 Log.e(TAG, "Unknown message type " + msg.what);
                 return;
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 5f6f754..1e508d2 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -256,6 +256,18 @@
 }
 
 static void
+android_media_MediaRecorder_setMaxDuration(JNIEnv *env, jobject thiz, jint max_duration_ms)
+{
+    LOGV("setMaxDuration(%d)", max_duration_ms);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+    char params[64];
+    sprintf(params, "max-duration=%d", max_duration_ms);
+
+    process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxDuration failed.");
+}
+
+static void
 android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
 {
     LOGV("prepare");
@@ -357,6 +369,7 @@
     {"_setOutputFile",       "(Ljava/io/FileDescriptor;JJ)V",   (void *)android_media_MediaRecorder_setOutputFileFD},
     {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
     {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
+    {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
     {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
     {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
     {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index f187bf5..84d08c4 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -44,6 +44,7 @@
     SET_OUTPUT_FILE_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
+    SET_PARAMETERS,
     SET_PREVIEW_SURFACE,
     SET_CAMERA,
     SET_LISTENER
@@ -178,6 +179,16 @@
         return reply.readInt32();
     }
 
+    status_t setParameters(const String8& params)
+    {
+        LOGV("setParameter(%s)", params.string());
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeString8(params);
+        remote()->transact(SET_PARAMETERS, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t setListener(const sp<IMediaPlayerClient>& listener)
     {
         LOGV("setListener(%p)", listener.get());
@@ -385,6 +396,12 @@
             reply->writeInt32(setVideoFrameRate(frames_per_second));
             return NO_ERROR;
         } break;
+        case SET_PARAMETERS: {
+            LOGV("SET_PARAMETER");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            reply->writeInt32(setParameters(data.readString8()));
+            return NO_ERROR;
+        } break;
         case SET_LISTENER: {
             LOGV("SET_LISTENER");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 572b1e7..23b3b9d 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -21,6 +21,7 @@
 #include <ui/Surface.h>
 #include <media/mediarecorder.h>
 #include <utils/IServiceManager.h>
+#include <utils/String8.h>
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 
@@ -356,6 +357,23 @@
     return ret;
 }
 
+status_t MediaRecorder::setParameters(const String8& params) {
+    LOGV("setParameters(%s)", params.string());
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setParameters(params);
+    if (OK != ret) {
+        LOGE("setParameters(%s) failed: %d", params.string(), ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return ret;
+    }
+
+    return ret;
+}
+
 status_t MediaRecorder::prepare()
 {
     LOGV("prepare");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 4b45acb..5d1887d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -154,6 +154,16 @@
     return mRecorder->setVideoFrameRate(frames_per_second);
 }
 
+status_t MediaRecorderClient::setParameters(const String8& params) {
+    LOGV("setParameters(%s)", params.string());
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setParameters(params);
+}
+
 status_t MediaRecorderClient::prepare()
 {
     LOGV("prepare");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 93fd802..6a1c2d5 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -39,6 +39,7 @@
     virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
     virtual     status_t        setVideoSize(int width, int height);
     virtual     status_t        setVideoFrameRate(int frames_per_second);
+    virtual     status_t        setParameters(const String8& params);
     virtual     status_t        setListener(const sp<IMediaPlayerClient>& listener);
     virtual     status_t        prepare();
     virtual     status_t        getMaxAmplitude(int* max);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
index 24edb65..05ac408 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioTrackTest.java
@@ -22,7 +22,6 @@
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioTrack;
-import android.content.Context;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -595,12 +594,12 @@
         //-------- tear down      --------------
         track.release();
     }
-/*    
-    //Test case 7: setPlaybackRate() clips values over twice the output sample rate
+    
+    //Test case 7: setPlaybackRate() and retrieve value, should be the same for half the content SR
     @LargeTest
-    public void testSetPlaybackRateClip() throws Exception {
+    public void testSetGetPlaybackRate() throws Exception {
         // constants for test
-        final String TEST_NAME = "testSetPlaybackRateClip";
+        final String TEST_NAME = "testSetGetPlaybackRate";
         final int TEST_SR = 22050;
         final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
@@ -612,18 +611,17 @@
         AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
                 minBuffSize, TEST_MODE);
         byte data[] = new byte[minBuffSize/2];
-        int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE);
         //--------    test        --------------
         track.write(data, 0, data.length);
         track.write(data, 0, data.length);
         assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
         track.play();
-        track.setPlaybackRate(3*outputSR);
-        assertTrue(TEST_NAME, track.getSampleRate() == 2*outputSR);
+        track.setPlaybackRate((int)(TEST_SR/2));
+        assertTrue(TEST_NAME, track.getPlaybackRate() == (int)(TEST_SR/2));
         //-------- tear down      --------------
         track.release();
     }
-*/    
+    
     //Test case 8: setPlaybackRate() invalid operation if track not initialized
     @LargeTest
     public void testSetPlaybackRateUninit() throws Exception {
@@ -641,7 +639,8 @@
                 minBuffSize, TEST_MODE);
         //--------    test        --------------
         assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA);
-        assertTrue(TEST_NAME, track.setPlaybackRate(TEST_SR/2) == AudioTrack.ERROR_INVALID_OPERATION);
+        assertTrue(TEST_NAME, 
+                track.setPlaybackRate(TEST_SR/2) == AudioTrack.ERROR_INVALID_OPERATION);
         //-------- tear down      --------------
         track.release();
     }
@@ -863,8 +862,7 @@
         //-------- tear down      --------------
         track.release();
     }
-/*    
-    //Test case 7: setLoopPoints() fails with start beyond what can be written for the track
+    //Test case 8: setLoopPoints() fails with start beyond what can be written for the track
     @LargeTest
     public void testSetLoopPointsStartTooFar() throws Exception {
         // constants for test
@@ -891,7 +889,327 @@
         //-------- tear down      --------------
         track.release();
     }
-*/    
+
+    //Test case 9: setLoopPoints() fails with end beyond what can be written for the track
+    @LargeTest
+    public void testSetLoopPointsEndTooFar() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testSetLoopPointsEndTooFar";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STATIC;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        int dataSizeInFrames = minBuffSize/2;//16bit data
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA);
+        track.write(data, 0, data.length);
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME, 
+                track.setLoopPoints(dataSizeInFrames-10, dataSizeInFrames+50, 2) 
+                    == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    
+    //-----------------------------------------------------------------
+    //      Audio data supply
+    //----------------------------------
+    
+    //Test case 1: write() fails when supplying less data (bytes) than declared
+    @LargeTest
+    public void testWriteByteOffsetTooBig() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByteOffsetTooBig";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 10, data.length) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 2: write() fails when supplying less data (shorts) than declared
+    @LargeTest
+    public void testWriteShortOffsetTooBig() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShortOffsetTooBig";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 10, data.length) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 3: write() fails when supplying less data (bytes) than declared
+    @LargeTest
+    public void testWriteByteSizeTooBig() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByteSizeTooBig";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length + 10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 4: write() fails when supplying less data (shorts) than declared
+    @LargeTest
+    public void testWriteShortSizeTooBig() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShortSizeTooBig";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length + 10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 5: write() fails with negative offset
+    @LargeTest
+    public void testWriteByteNegativeOffset() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByteNegativeOffset";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, -10, data.length - 10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 6: write() fails with negative offset
+    @LargeTest
+    public void testWriteShortNegativeOffset() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShortNegativeOffset";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, -10, data.length - 10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 7: write() fails with negative size
+    @LargeTest
+    public void testWriteByteNegativeSize() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByteNegativeSize";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, -10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 8: write() fails with negative size
+    @LargeTest
+    public void testWriteShortNegativeSize() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShortNegativeSize";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, -10) == AudioTrack.ERROR_BAD_VALUE);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 9: write() succeeds and returns the size that was written for 16bit
+    @LargeTest
+    public void testWriteByte() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByte";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length) == data.length);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 10: write() succeeds and returns the size that was written for 16bit
+    @LargeTest
+    public void testWriteShort() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShort";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length) == data.length);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 11: write() succeeds and returns the size that was written for 8bit
+    @LargeTest
+    public void testWriteByte8bit() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteByte8bit";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        byte data[] = new byte[minBuffSize];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length) == data.length);
+        //-------- tear down      --------------
+        track.release();
+    }
+    
+    //Test case 12: write() succeeds and returns the size that was written for 8bit
+    @LargeTest
+    public void testWriteShort8bit() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testWriteShort8bit";
+        final int TEST_SR = 22050;
+        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+        
+        //-------- initialization --------------
+        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 
+                2*minBuffSize, TEST_MODE);
+        short data[] = new short[minBuffSize/2];
+        //--------    test        --------------
+        assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+        assertTrue(TEST_NAME,
+                track.write(data, 0, data.length) == data.length);
+        //-------- tear down      --------------
+        track.release();
+    }
     
 }
 
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 72d88e2..275ff3a 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -26,7 +26,7 @@
     <bool name="def_accelerometer_rotation">true</bool>
     <!-- Default screen brightness, from 0 to 255.  102 is 40%. -->
     <integer name="def_screen_brightness">102</integer>
-    <fraction name="def_window_animation_scale">0%</fraction>
+    <fraction name="def_window_animation_scale">100%</fraction>
     <fraction name="def_window_transition_scale">0%</fraction>
     
     <bool name="def_bluetooth_on">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 2f32ab7..d39934b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -334,7 +334,8 @@
 
         if (upgradeVersion == 31) {
             /*
-             * Animations are now turned off by default.
+             * Animations are now managed in preferences, and may be
+             * enabled or disabled based on product resources.
              */
             db.beginTransaction();
             try {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 8814e48..f81c519 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -82,6 +82,8 @@
 
     private boolean mMounted;
 
+    private boolean mAutoStartUms;
+
     /**
      * Constructs a new MountService instance
      * 
@@ -100,6 +102,8 @@
         mShowSafeUnmountNotificationWhenUnmounted = false;
 
         mPlaySounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
+
+        mAutoStartUms = SystemProperties.get("persist.service.mount.umsauto", "0").equals("1");
     }
 
     BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -198,6 +202,26 @@
     }
 
     /**
+     * Returns true if we auto-start UMS on cable insertion.
+     */
+    public boolean getAutoStartUms() {
+        return mAutoStartUms;
+    }
+
+    /**
+     * Set whether or not we're playing media notification sounds.
+     */
+    public void setAutoStartUms(boolean enabled) {
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_SETTINGS) 
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires WRITE_SETTINGS permission");
+        }
+        mAutoStartUms = enabled;
+        SystemProperties.set("persist.service.mount.umsauto", (enabled ? "1" : "0"));
+    }
+
+    /**
      * Update the state of the USB mass storage notification
      */
     void updateUsbMassStorageNotification(boolean suppressIfConnected, boolean sound) {
@@ -239,7 +263,14 @@
             !storageState.equals(Environment.MEDIA_BAD_REMOVAL) &&
             !storageState.equals(Environment.MEDIA_CHECKING)) {
 
-            updateUsbMassStorageNotification(false, true);
+            if (mAutoStartUms) {
+                try {
+                    setMassStorageEnabled(true);
+                } catch (RemoteException e) {
+                }
+            } else {
+                updateUsbMassStorageNotification(false, true);
+            }
         }
 
         Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index fec3608..9f428e9 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -5460,6 +5460,12 @@
                         // has to delete the one installed in the data partition in order to pick up the
                         // new system package.
                         return p;
+                    } else if ((p.pkg != null) && (p.pkg.applicationInfo != null) &&
+                                ((p.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
+                        // Check for non-system apps
+                        reportSettingsProblem(Log.WARN,
+                                "Package " + name + " codePath changed from " + p.codePath
+                                + " to " + codePath + "; Retaining data and using new code");
                     } else {
                         reportSettingsProblem(Log.WARN,
                                 "Package " + name + " codePath changed from " + p.codePath
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 5e5fb93..a74915c 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -28,6 +28,7 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.io.FileDescriptor;
@@ -187,6 +188,9 @@
     }
 
     public void notifyCallState(int state, String incomingNumber) {
+        if (!checkPhoneStatePermission("notifyCallState()")) {
+            return;
+        }
         synchronized (mRecords) {
             mCallState = state;
             mCallIncomingNumber = incomingNumber;
@@ -206,6 +210,9 @@
     }
 
     public void notifyServiceState(ServiceState state) {
+        if (!checkPhoneStatePermission("notifyServiceState()")) {
+            return;
+        }      
         synchronized (mRecords) {
             mServiceState = state;
             final int N = mRecords.size();
@@ -220,6 +227,9 @@
     }
 
     public void notifySignalStrength(int signalStrengthASU) {
+        if (!checkPhoneStatePermission("notifySignalStrength()")) {
+            return;
+        }      
         synchronized (mRecords) {
             mSignalStrength = signalStrengthASU;
             final int N = mRecords.size();
@@ -238,6 +248,9 @@
     }
 
     public void notifyMessageWaitingChanged(boolean mwi) {
+        if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
+            return;
+        }      
         synchronized (mRecords) {
             mMessageWaiting = mwi;
             final int N = mRecords.size();
@@ -255,6 +268,9 @@
     }
 
     public void notifyCallForwardingChanged(boolean cfi) {
+        if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
+            return;
+        }   
         synchronized (mRecords) {
             mCallForwarding = cfi;
             final int N = mRecords.size();
@@ -272,6 +288,9 @@
     }
 
     public void notifyDataActivity(int state) {
+        if (!checkPhoneStatePermission("notifyDataActivity()")) {
+            return;
+        }   
         synchronized (mRecords) {
             mDataActivity = state;
             final int N = mRecords.size();
@@ -290,6 +309,9 @@
 
     public void notifyDataConnection(int state, boolean isDataConnectivityPissible,
             String reason, String apn, String interfaceName) {
+        if (!checkPhoneStatePermission("notifyDataConnection()")) {
+            return;
+        }   
         synchronized (mRecords) {
             mDataConnectionState = state;
             mDataConnectionPossible = isDataConnectivityPissible;
@@ -313,6 +335,9 @@
     }
 
     public void notifyDataConnectionFailed(String reason) {
+        if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
+            return;
+        }   
         /*
          * This is commented out because there is on onDataConnectionFailed callback
          * on PhoneStateListener.  There should be.
@@ -331,6 +356,9 @@
     }
 
     public void notifyCellLocation(Bundle cellLocation) {
+        if (!checkPhoneStatePermission("notifyCellLocation()")) {
+            return;
+        } 
         synchronized (mRecords) {
             mCellLocation = cellLocation;
             final int N = mRecords.size();
@@ -459,4 +487,16 @@
         intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
         mContext.sendStickyBroadcast(intent);
     }
+    
+    private boolean checkPhoneStatePermission(String method) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+        String msg = "Modify Phone State Permission Denial: " + method + " from pid="
+                + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid();
+        Log.w(TAG, msg);
+        return false;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index adc8bc1..05e61f2 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -140,6 +140,7 @@
     static final String REASON_VOICE_CALL_STARTED = "2GVoiceCallStarted";
     static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
     static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
+    static final String REASON_SIM_LOADED = "simLoaded";
     
     // Used for band mode selection methods
     static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 66fa943..2b70162 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -16,11 +16,12 @@
 
 package com.android.internal.telephony;
 
+import android.content.Context;
 import android.content.Intent;
+import android.os.PowerManager;
 import android.provider.Telephony.Sms.Intents;
 import android.util.Config;
 import android.util.Log;
-import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.gsm.SimUtils;
 
 
@@ -32,12 +33,19 @@
 public class WapPushOverSms {
     private static final String LOG_TAG = "WAP PUSH";
 
-    private final GSMPhone mPhone;
+    private final Context mContext;
     private WspTypeDecoder pduDecoder;
+    private PowerManager.WakeLock mWakeLock;
 
+    /**
+     * Hold the wake lock for 5 seconds, which should be enough time for 
+     * any receiver(s) to grab its own wake lock.
+     */
+    private final int WAKE_LOCK_TIMEOUT = 5000;
 
-    public WapPushOverSms(GSMPhone phone) {
-        mPhone = phone;
+    public WapPushOverSms(Phone phone) {
+        mContext = phone.getContext();
+        createWakelock();
     }
 
     /**
@@ -163,8 +171,6 @@
         }
     }
 
-
-
     private void dispatchWapPdu_default(
             byte[] pdu, int transactionId, int pduType, String mimeType, int dataIndex) {
         byte[] data;
@@ -178,8 +184,7 @@
         intent.putExtra("pduType", pduType);
         intent.putExtra("data", data);
 
-        mPhone.getContext().sendBroadcast(
-                intent, "android.permission.RECEIVE_WAP_PUSH");
+        sendBroadcast(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
     private void dispatchWapPdu_PushCO(byte[] pdu, int transactionId, int pduType) {
@@ -189,8 +194,7 @@
         intent.putExtra("pduType", pduType);
         intent.putExtra("data", pdu);
 
-        mPhone.getContext().sendBroadcast(
-                intent, "android.permission.RECEIVE_WAP_PUSH");
+        sendBroadcast(intent, "android.permission.RECEIVE_WAP_PUSH");
     }
 
     private void dispatchWapPdu_MMS(byte[] pdu, int transactionId, int pduType, int dataIndex) {
@@ -205,7 +209,19 @@
         intent.putExtra("pduType", pduType);
         intent.putExtra("data", data);
 
-        mPhone.getContext().sendBroadcast(
-                intent, "android.permission.RECEIVE_MMS");
+        sendBroadcast(intent, "android.permission.RECEIVE_MMS");
+    }
+
+    private void createWakelock() {
+        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WapPushOverSms");
+        mWakeLock.setReferenceCounted(true);
+    }
+
+    private void sendBroadcast(Intent intent, String permission) {
+        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
+        // receivers time to take their own wake locks.
+        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
+        mContext.sendBroadcast(intent, permission);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
index e664bc7..30b1be8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
@@ -199,9 +199,9 @@
     private static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
 
     /** Default ping deadline, in seconds. */
-    private final int DEFAULT_PING_DEADLINE = 5;
+    private static final int DEFAULT_PING_DEADLINE = 5;
     /** Default max failure count before attempting to network re-registration. */
-    private final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
+    private static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
 
     /**
      * After detecting a potential connection problem, this is the max number
@@ -677,8 +677,7 @@
         if ((state == State.IDLE || state == State.SCANNING)
                 && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
                 && phone.mSIMRecords.getRecordsLoaded()
-                && ( phone.mSST.isConcurrentVoiceAndData() ||
-                     phone.getState() == Phone.State.IDLE )
+                && phone.getState() == Phone.State.IDLE
                 && isDataAllowed()
                 && !mIsPsRestricted ) {
 
@@ -1351,7 +1350,7 @@
                 if (state == State.FAILED) {
                     cleanUpConnection(false, null);
                 }
-                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
                 break;
 
             case EVENT_ENABLE_NEW_APN:
@@ -1362,6 +1361,10 @@
                 break;
 
             case EVENT_TRY_SETUP_DATA:
+                if (msg.obj instanceof String) {
+                    reason = (String)msg.obj;
+                }
+
                 trySetupData(reason);
                 break;
 
@@ -1500,7 +1503,10 @@
                         } else {
                             // we still have more apns to try
                             setState(State.SCANNING);
-                            trySetupData(reason);
+                            // Wait a bit before trying the next APN, so that 
+                            // we're not tying up the RIL command channel
+                            sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason),
+                                    RECONNECT_DELAY_INITIAL_MILLIS);
                         }
                     } else {
                         startDelayedRetry(cause, reason);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
index 877b734..5585524 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
@@ -32,6 +32,7 @@
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.provider.Telephony;
 import android.provider.Settings;
 import android.provider.Telephony.Sms.Intents;
@@ -122,6 +123,15 @@
 
     private SmsTracker mSTracker;
 
+    /** Wake lock to ensure device stays awake while dispatching the SMS intent. */
+    private PowerManager.WakeLock mWakeLock;
+
+    /**
+     * Hold the wake lock for 5 seconds, which should be enough time for 
+     * any receiver(s) to grab its own wake lock.
+     */
+    private final int WAKE_LOCK_TIMEOUT = 5000;
+
     /**
      *  Implement the per-application based SMS control, which only allows
      *  a limit on the number of SMS/MMS messages an app can send in checking
@@ -186,6 +196,8 @@
         mCm = phone.mCM;
         mSTracker = null;
 
+        createWakelock();
+
         int check_period = Settings.Gservices.getInt(mResolver,
                 Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
                 DEFAULT_SMS_CHECK_PERIOD);
@@ -286,6 +298,19 @@
         }
     }
 
+    private void createWakelock() {
+        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSDispatcher");
+        mWakeLock.setReferenceCounted(true);
+    }
+
+    private void sendBroadcast(Intent intent, String permission) {
+        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
+        // receivers time to take their own wake locks.
+        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
+        mContext.sendBroadcast(intent, permission);
+    }
+
     /**
      * Called when SIM_FULL message is received from the RIL.  Notifies interested
      * parties that SIM storage for SMS messages is full.
@@ -293,7 +318,7 @@
     private void handleSimFull() {
         // broadcast SIM_FULL intent
         Intent intent = new Intent(Intents.SIM_FULL_ACTION);
-        mPhone.getContext().sendBroadcast(intent, "android.permission.RECEIVE_SMS");
+        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
     /**
@@ -633,8 +658,7 @@
     private void dispatchPdus(byte[][] pdus) {
         Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
         intent.putExtra("pdus", pdus);
-        mPhone.getContext().sendBroadcast(
-                intent, "android.permission.RECEIVE_SMS");
+        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
     /**
@@ -647,8 +671,7 @@
         Uri uri = Uri.parse("sms://localhost:" + port);
         Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
         intent.putExtra("pdus", pdus);
-        mPhone.getContext().sendBroadcast(
-                intent, "android.permission.RECEIVE_SMS");
+        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
index 7152f76..89ce506 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
@@ -1511,7 +1511,7 @@
                         + (c.getTimeInMillis() - System.currentTimeMillis())
                         + " from " + nitz);
 
-                    SystemClock.setCurrentTimeMillis(c.getTimeInMillis());
+                    setAndBroadcastNetworkSetTime(c.getTimeInMillis());
                     Log.i(LOG_TAG, "NITZ: after Setting time of day");
                 }
                 SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
diff --git a/tests/CoreTests/android/webkit/CookieTest.java b/tests/CoreTests/android/webkit/CookieTest.java
index 1c3d671..ea4422f 100644
--- a/tests/CoreTests/android/webkit/CookieTest.java
+++ b/tests/CoreTests/android/webkit/CookieTest.java
@@ -55,6 +55,11 @@
         mCookieManager.setCookie(url, "c=\"d;\"");
         cookie = mCookieManager.getCookie(url);
         assertTrue(cookie.equals("a=b; c=\"d;\""));
+
+        // empty
+        mCookieManager.setCookie(url, "; path=/");
+        cookie = mCookieManager.getCookie(url);
+        assertTrue(cookie.equals("a=b; c=\"d;\""));
     }
 
     public void testDomain() {
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 8e06cc8..17c44ad 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -23,7 +23,7 @@
                 <category android:name="android.intent.category.TEST" />
             </intent-filter>
         </activity>
-        <activity android:name="HTMLHostActivity">
+        <activity android:name="TestShellActivity" android:launchMode="singleTop">
         </activity>
     </application>
 
diff --git a/tests/DumpRenderTree/compare_layout_results.py b/tests/DumpRenderTree/compare_layout_results.py
deleted file mode 100644
index c4285f1..0000000
--- a/tests/DumpRenderTree/compare_layout_results.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python
-"""
-Compares results of two webkit layout test runs and writes
-results to a file.
-"""
-
-import optparse
-import os
-import sys
-
-def DiffResults(marker, new_results, old_results, diff_results, strip_reason):
-   """ Given two result files, generate diff and
-       write to diff_results file. All arguments are absolute paths
-       to files.
-   """
-   old_file = open(old_results, "r")
-   new_file = open(new_results, "r")
-   diff_file = open(diff_results, "a") 
-
-   # Read lines from each file
-   ndict = new_file.readlines()
-   cdict = old_file.readlines()
-
-   # Write marker to diff file
-   diff_file.writelines(marker + "\n")
-   diff_file.writelines("###############\n")
-
-   # Strip reason from result lines
-   if strip_reason is True:
-     for i in range(0, len(ndict)):
-       ndict[i] = ndict[i].split(' ')[0] + "\n"
-     for i in range(0, len(cdict)):
-       cdict[i] = cdict[i].split(' ')[0] + "\n"
-
-   # Find results in new_results missing in old_results
-   new_count=0
-   for line in ndict:
-     if line not in cdict:
-       diff_file.writelines("+ " + line)
-       new_count += 1
-
-   # Find results in old_results missing in new_results
-   missing_count=0
-   for line in cdict:
-     if line not in ndict:
-       diff_file.writelines("- " + line)
-       missing_count += 1
-
-   print marker + "  >>> added " + str(new_count) + " tests, removed " + str(missing_count) + " tests" 
-
-   diff_file.writelines("\n\n")
-
-   old_file.close()
-   new_file.close()
-   diff_file.close()
-   return
-
-def main(options, args):
-  results_dir = os.path.abspath(options.results_directory)
-  ref_dir = options.ref_directory
-
-  # if ref_dir is null, cannonify ref_dir to the script dir.
-  if not ref_dir:
-    script_self = sys.argv[0]
-    script_dir = os.path.dirname(script_self)
-    ref_dir = os.path.join(script_dir, "results")
-
-  ref_dir = os.path.abspath(ref_dir)
-
-  diff_result = os.path.join(results_dir, "layout_tests_diff.txt") 
-  if os.path.exists(diff_result):
-    os.remove(diff_result)
-
-  files=["passed", "failed", "nontext", "crashed"]
-  for f in files:
-    result_file_name = "layout_tests_" + f + ".txt"
-    DiffResults(f, os.path.join(results_dir, result_file_name),
-                os.path.join(ref_dir, result_file_name), diff_result,
-                f == "failed")
-
-if '__main__' == __name__:
-  option_parser = optparse.OptionParser()
-  option_parser.add_option("", "--ref-directory",
-                           default=None,
-                           dest="ref_directory",
-                           help="directory name under which results are stored.")
-
-  option_parser.add_option("", "--results-directory",
-                           default="layout-test-results/",
-                           dest="results_directory",
-                           help="directory name under which results are stored.")
-  options, args = option_parser.parse_args()
-  main(options, args)
diff --git a/tests/DumpRenderTree/run_layout_tests.py b/tests/DumpRenderTree/run_layout_tests.py
index 433271e..5409a0c 100755
--- a/tests/DumpRenderTree/run_layout_tests.py
+++ b/tests/DumpRenderTree/run_layout_tests.py
@@ -22,6 +22,7 @@
   use --refresh-test-list option *once* to re-generate test list on the card.
 
   Some other options are:
+    --rebaseline generates expected layout tests results under /sdcard/android/expected_result/ 
     --time-out-ms (default is 8000 millis) for each test
     --adb-options="-e" passes option string to adb
     --results-directory=..., (default is ./layout-test-results) directory name under which results are stored.
@@ -55,8 +56,8 @@
     output: adb_cmd string
   """
   
-  # pull /sdcard/running_test.txt, if the content is "#DONE", it's done
-  shell_cmd_str = adb_cmd + " shell cat /sdcard/running_test.txt"
+  # pull /sdcard/android/running_test.txt, if the content is "#DONE", it's done
+  shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
   adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
   return adb_output.strip() == "#DONE"
 
@@ -145,7 +146,7 @@
 
   # Include all tests if none are specified.
   if not args:
-    path = 'fast';
+    path = '/';
   else:
     path = ' '.join(args);
 
@@ -156,8 +157,8 @@
   # Re-generate the test list if --refresh-test-list is on
   if options.refresh_test_list:
     logging.info("Generating test list.");
-    shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#generateTestList -e path fast -w com.android.dumprendertree/.LayoutTestsAutoRunner"
-    adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
+    generate_test_list_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#generateTestList -e path \"" + path + "\" -w com.android.dumprendertree/.LayoutTestsAutoRunner"
+    adb_output = subprocess.Popen(generate_test_list_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
 
     if adb_output.find('Process crashed') != -1:
        logging.info("Aborting because cannot generate test list.\n" + adb_output)
@@ -169,20 +170,28 @@
   # Count crashed tests.
   crashed_tests = []
 
-  timeout_ms = '8000'
+  timeout_ms = '5000'
   if options.time_out_ms:
     timeout_ms = options.time_out_ms
 
   # Run test until it's done
 
+  run_layout_test_cmd_prefix = adb_cmd + " shell am instrument"
+
+  run_layout_test_cmd_postfix = " -e path \"" + path + "\" -e timeout " + timeout_ms
+  if options.rebaseline:
+    run_layout_test_cmd_postfix += " -e rebaseline true"
+  run_layout_test_cmd_postfix += " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
+
   # Call LayoutTestsAutoTest::startLayoutTests.
-  shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#startLayoutTests -e path \"" + path + "\" -e timeout " + timeout_ms + " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
-  adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
+  run_layout_test_cmd = run_layout_test_cmd_prefix + " -e class com.android.dumprendertree.LayoutTestsAutoTest#startLayoutTests" + run_layout_test_cmd_postfix
+
+  adb_output = subprocess.Popen(run_layout_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
   while not DumpRenderTreeFinished(adb_cmd):
     # Get the running_test.txt
     logging.error("DumpRenderTree crashed, output:\n" + adb_output)
 
-    shell_cmd_str = adb_cmd + " shell cat /sdcard/running_test.txt"
+    shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
     crashed_test = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE).communicate()[0]
     
     logging.info(crashed_test + " CRASHED");
@@ -190,9 +199,9 @@
 
     logging.info("Resuming layout test runner...");
     # Call LayoutTestsAutoTest::resumeLayoutTests
-    shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#resumeLayoutTests -e path \"" + path + "\" -e timeout " + timeout_ms + " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
+    run_layout_test_cmd = run_layout_test_cmd_prefix + " -e class com.android.dumprendertree.LayoutTestsAutoTest#resumeLayoutTests" + run_layout_test_cmd_postfix
 
-    adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
+    adb_output = subprocess.Popen(run_layout_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
 
   if adb_output.find('INSTRUMENTATION_FAILED') != -1:
     logging.error("Error happened : " + adb_output)
@@ -219,7 +228,7 @@
     
   # Create the crash list.
   fp = open(results_dir + "/layout_tests_crashed.txt", "w");
-  fp.writelines(crashed_tests)
+  fp.writelines('\n'.join(crashed_tests))
   fp.close()
 
   # Count the number of tests in each category.
@@ -250,6 +259,9 @@
 
 if '__main__' == __name__:
   option_parser = optparse.OptionParser()
+  option_parser.add_option("", "--rebaseline", action="store_true",
+                           default=False,
+                           help="generate expected results for those tests not having one")
   option_parser.add_option("", "--time-out-ms",
                            default=None,
                            help="set the timeout for each test")
diff --git a/tests/DumpRenderTree/run_page_cycler.py b/tests/DumpRenderTree/run_page_cycler.py
new file mode 100755
index 0000000..9a099b5
--- /dev/null
+++ b/tests/DumpRenderTree/run_page_cycler.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+
+"""Run page cycler tests using Android instrumentation.
+
+  First, you need to get an SD card or sdcard image that has page cycler tests.
+
+  Usage:
+    Run a single page cycler test:
+      run_page_cycler.py "file:///sdcard/android/page_cycler/moz/start.html?auto=1\&iterations=10"
+"""
+
+import logging
+import optparse
+import os
+import subprocess
+import sys
+import time
+
+
+
+def main(options, args):
+  """Run the tests. Will call sys.exit when complete.
+  
+  """
+
+  # Set up logging format.
+  log_level = logging.INFO
+  if options.verbose:
+    log_level = logging.DEBUG
+  logging.basicConfig(level=log_level,
+                      format='%(message)s')
+
+  # Include all tests if none are specified.
+  if not args:
+    print "need a URL, e.g. file:///sdcard/android/page_cycler/moz/start.html"
+    sys.exit(1)
+  else:
+    path = ' '.join(args);
+
+  adb_cmd = "adb ";
+  if options.adb_options:
+    adb_cmd += options.adb_options
+
+  logging.info("Running the test ...")
+
+  # Count crashed tests.
+  crashed_tests = []
+
+  timeout_ms = '0'
+  if options.time_out_ms:
+    timeout_ms = options.time_out_ms
+
+  # Run test until it's done
+
+  run_load_test_cmd_prefix = adb_cmd + " shell am instrument"
+  run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
+
+  # Call LoadTestsAutoTest::runTest.
+  run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix
+
+  (adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+  if adb_output.find('INSTRUMENTATION_FAILED') != -1:
+    logging.error("Error happened : " + adb_output)
+    sys.exit(1)
+
+  logging.info(adb_output);
+  logging.info(adb_error);
+  logging.info("Done\n");
+
+  # Pull results from /sdcard/load_test_result.txt
+  results_dir = options.results_directory
+  if not os.path.exists(results_dir):
+    os.makedirs(results_dir)
+  if not os.path.isdir(results_dir):
+    logging.error("Cannot create results dir: " + results_dir)
+    sys.exit(1)
+
+  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)
+    
+  logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n")
+
+if '__main__' == __name__:
+  option_parser = optparse.OptionParser()
+  option_parser.add_option("", "--time-out-ms",
+                           default=None,
+                           help="set the timeout for each test")
+  option_parser.add_option("", "--verbose", action="store_true",
+                           default=False,
+                           help="include debug-level logging")
+  option_parser.add_option("", "--adb-options",
+                           default=None,
+                           help="pass options to adb, such as -d -e, etc");
+  option_parser.add_option("", "--results-directory",
+                           default="layout-test-results",
+                           help="directory which results are stored.")
+
+  options, args = option_parser.parse_args();
+  main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 9be33db..4f162b3 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -75,31 +75,14 @@
         ".", // ignore hidden directories and files
         "resources", // ignore resource directories
         "AppleScript", // AppleScript not supported
-        "xpath", // xpath requires libxml2, not supported
-        "xsl", //xsl requires libxml2 & libxslt, not sup.
-        "kde", // don't run kde tests.
         ".svn", // don't run anything under .svn folder
-        "gradients", // known crash
-        "profiler"  // profiler is not supported
+        "profiler",  // profiler is not supported
+        "svg",  // svg is not supported
+        "platform",  // platform specific
+        "http"  // requires local http(s) server
     };
         
     static final String [] ignoreTestList = {
-        "toString-stack-overflow.html", // Crashes #606688
-        "frame-limit.html", // generates too many GREFs
-        "css-insert-import-rule.html", // Crashes, #717414
-        "input-text-enter.html", // Crashes. #735088
-        "text-shadow-extreme-value.html", // Crashes #571671
-        "reflection-masks.html",
-        "frame-creation-removal.html",
-        "large-expressions.html",
-        "null-page-show-modal-dialog-crash.html",
-        "font-face-implicit-local-font.html",
-        "font-face-locally-installed.html",
-        "beforeSelectorOnCodeElement.html",
-        "cssTarget-crash.html",
-        "searchfield-heights.html", // Bug 1570692
-        "tabindex-focus-blur-all.html",
-        "search-rtl.html" // fast/forms/search-rtl.html
         };
     
     static void fillIgnoreResultSet() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
index d685f5d..0218317 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
@@ -17,6 +17,7 @@
 package com.android.dumprendertree;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -84,7 +85,8 @@
         	return myData;
         }
         String[] files = f.list();
- 
+        Arrays.sort(files);
+
         for (int i = 0; i < files.length; i++) {
         	StringBuilder sb = new StringBuilder(mPath);
         	sb.append(File.separatorChar);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
deleted file mode 100644
index 86bfad7..0000000
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dumprendertree;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileInputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.List;
-import java.util.Vector;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.ViewGroup;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.widget.LinearLayout;
-import android.os.*;
-
-// TestRecorder creates two files, one for passing tests
-// and another for failing tests and writes the paths to
-// layout tests one line at a time. TestRecorder does not
-// have ability to clear the results.
-class TestRecorder {
-    public void passed(String layout_file) {
-      try {
-          mBufferedOutputPassedStream.write(layout_file.getBytes());
-          mBufferedOutputPassedStream.write('\n');
-          mBufferedOutputPassedStream.flush();
-      } catch(Exception e) {
-          e.printStackTrace();
-      }
-   }
-
-    public void failed(String layout_file, String reason) {
-      try {
-          mBufferedOutputFailedStream.write(layout_file.getBytes());
-          mBufferedOutputFailedStream.write(" : ".getBytes());
-          mBufferedOutputFailedStream.write(reason.getBytes());
-          mBufferedOutputFailedStream.write('\n');
-          mBufferedOutputFailedStream.flush();
-      } catch(Exception e) {
-          e.printStackTrace();
-      }
-    }
-
-    public void nontext(String layout_file, boolean has_results) {
-      try {
-          mBufferedOutputNontextStream.write(layout_file.getBytes());
-          if (has_results) {
-              mBufferedOutputNontextStream.write(" : has expected results".getBytes());
-          }
-          mBufferedOutputNontextStream.write('\n');
-          mBufferedOutputNontextStream.flush();
-      } catch(Exception e) {
-          e.printStackTrace();
-      }
-    }
-
-    public TestRecorder(boolean resume) {
-      try {
-      File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt");
-      File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt");
-      File resultsNontextFile = new File("/sdcard/layout_tests_nontext.txt");
- 
-      mBufferedOutputPassedStream =
-          new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume));
-      mBufferedOutputFailedStream =
-          new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume));
-      mBufferedOutputNontextStream =
-          new BufferedOutputStream(new FileOutputStream(resultsNontextFile, resume));
-      } catch (Exception e) {
-          e.printStackTrace();
-      }
-    }
-
-    public void close() {
-        try {
-            mBufferedOutputPassedStream.close();
-            mBufferedOutputFailedStream.close();
-            mBufferedOutputNontextStream.close();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-    private BufferedOutputStream mBufferedOutputPassedStream;
-    private BufferedOutputStream mBufferedOutputFailedStream;
-    private BufferedOutputStream mBufferedOutputNontextStream;
-}
-
-public class HTMLHostActivity extends Activity 
-     implements LayoutTestController {
-
-    public class AsyncHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            if (msg.what == MSG_TIMEOUT) {
-                mTimedOut = true;
-                requestWebKitData();
-                return;
-            } else if (msg.what == MSG_WEBKIT_DATA) {
-                HTMLHostActivity.this.dump(mTimedOut, (String)msg.obj);
-                return;
-            }
-
-            super.handleMessage(msg);
-        }
-    }
-
-    public void requestWebKitData() {
-        Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA);
-        
-        if (mRequestedWebKitData)
-            throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl());
-        
-        mRequestedWebKitData = true;
-        if (mDumpAsText) { 
-            mWebView.documentAsText(callback);
-        } else {
-            mWebView.externalRepresentation(callback);
-        }
-    }
-    // Activity methods
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        LinearLayout contentView = new LinearLayout(this);
-        contentView.setOrientation(LinearLayout.VERTICAL);
-        setContentView(contentView);
-
-        mWebView = new WebView(this);
-        mWebView.getSettings().setJavaScriptEnabled(true);
-        mWebView.setWebChromeClient(mChromeClient);
-        mEventSender = new WebViewEventSender(mWebView);
-        mCallbackProxy = new CallbackProxy(mEventSender, this);
-        mFinishedRunning = false;
-
-        mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController");
-        mWebView.addJavascriptInterface(mCallbackProxy, "eventSender");
-        contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
- 
-        mHandler = new AsyncHandler();
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
-        super.onRestoreInstanceState(savedInstanceState);
-    }
-
-    private void getTestList() {
-        // Read test list.
-        try {
-            BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE));
-            String line = inReader.readLine();
-            while (line != null) {
-                if (line.startsWith(mTestPathPrefix))
-                    mTestList.add(line);
-                line = inReader.readLine();
-            }
-            inReader.close();
-            Log.v(LOGTAG, "Test list has " + mTestList.size() + " test(s).");
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Error while reading test list : " + e.getMessage());
-        }
-    }
-    
-    private void resumeTestList() {
-        // read out the test name it stoped last time.
-        try {
-            BufferedReader inReader = new BufferedReader(new FileReader(TEST_STATUS_FILE));
-            String line = inReader.readLine();
-            for (int i = 0; i < mTestList.size(); i++) {
-                if (mTestList.elementAt(i).equals(line)) {
-                    mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size()));
-                    break;
-                }
-            }
-            inReader.close();
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE);
-        }
-    }
-    
-    private void clearTestStatus() {
-        // Delete TEST_STATUS_FILE
-        try {
-            File f = new File(TEST_STATUS_FILE);
-            if (f.delete())
-                Log.v(LOGTAG, "Deleted " + TEST_STATUS_FILE);
-            else
-                Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE);
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE + " : " + e.getMessage());
-        }
-    }
-    
-    private void updateTestStatus(String s) {
-        // Write TEST_STATUS_FILE
-        try {
-            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(TEST_STATUS_FILE));
-            bos.write(s.getBytes());
-            bos.close();
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Cannot update file " + TEST_STATUS_FILE);
-        }
-    }
-    
-    protected void onResume() {
-        super.onResume();
-        if (mTestList == null)
-            mTestList = new Vector<String>();
-        
-        if (mTestList.isEmpty()) {
-            // Read settings
-            Intent intent = getIntent();
-            mTestPathPrefix = intent.getStringExtra(TEST_PATH_PREFIX);
-            mSingleTestMode = intent.getBooleanExtra(SINGLE_TEST_MODE, false);
-            boolean resume = intent.getBooleanExtra(RESUME_FROM_CRASH, false);
-            mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 8000);
-            
-            mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
-            
-            if (mTestPathPrefix == null)
-                throw new AssertionError("mTestPathPrefix cannot be null");
-            
-            Log.v(LOGTAG, "Run tests with prefix: " + mTestPathPrefix);
-
-            mResultRecorder = new TestRecorder(resume);
-            
-            if (!resume)
-                clearTestStatus();
-            
-            if (!mSingleTestMode) {
-                getTestList();
-                if (resume)
-                    resumeTestList();
-            } else {
-                mTestList.add(mTestPathPrefix);
-            }
-            
-            if (!mTestList.isEmpty())
-                runTestAtIndex(0);
-            else
-                mWebView.loadUrl("about:");
-        }
-    }
-
-    protected void onStop() {
-        super.onStop();
-        mWebView.stopLoading();
-    }
-
-    protected void onDestroy() {
-        super.onDestroy();
-        mResultRecorder.close();
-        mWebView.destroy();
-        mWebView = null;
-    }
-    
-    public void onLowMemory() {
-        super.onLowMemory();
-        // Simulate a crash
-        Log.e(LOGTAG, "Low memory, killing self");
-        System.exit(1);
-    }
-
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        // Log key strokes as they don't seem to be matched
-        //Log.e(LOGTAG, "Event: "+event);
-        return super.dispatchKeyEvent(event);
-    }
-
-    // Run a test at specified index in the test list.
-    // Stops activity if run out of tests.
-    protected void runTestAtIndex(int testIndex) {
-        mTestIndex = testIndex;
-        
-        resetTestStatus();
-
-        if (testIndex == mTestList.size()) {
-            if (!mSingleTestMode) {
-                updateTestStatus("#DONE");
-            }
-            finished();
-            return;
-        }
-        String s = mTestList.elementAt(testIndex);
-        if (!mSingleTestMode)
-            updateTestStatus(s);
-        
-        Log.v(LOGTAG, "  Running test: "+s);
-        mWebView.loadUrl("file://"+s);
-        
-        if (!mSingleTestMode) {
-            // Create a timeout timer
-            Message m = mHandler.obtainMessage(MSG_TIMEOUT);
-            mHandler.sendMessageDelayed(m, mTimeoutInMillis);
-        }
-    }
-
-    // Dump the page
-    public void dump(boolean timeout, String webkitData) {
-        String currentTest = mTestList.elementAt(mTestIndex);
-        String resultFile = currentTest.substring(0, currentTest.lastIndexOf('.'));
-
-        // dumpAsText version can be directly compared to expected results
-        if (mDumpAsText) {
-            resultFile += "-results.txt";
-        } else {
-            resultFile += "-android-results.txt";
-        }
-
-        try {
-            FileOutputStream os = new FileOutputStream(resultFile);
-            if (timeout) {
-                Log.w("Layout test: Timeout", resultFile);
-                os.write(TIMEOUT_STR.getBytes());
-                os.write('\n');
-            }
-            if (mDumpTitleChanges)
-                os.write(mTitleChanges.toString().getBytes());
-            if (mDialogStrings != null)
-                os.write(mDialogStrings.toString().getBytes());
-            mDialogStrings = null;
-            os.write(webkitData.getBytes());
-            os.flush();
-            os.close();
-        } catch (FileNotFoundException ex) {
-            ex.printStackTrace();
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }
-
-        processResult(timeout, currentTest);
-        runTestAtIndex(mTestIndex + 1);
-    }
-
-    // Wrap up
-    public void failedCase(String file, String reason) {
-        Log.w("Layout test: ", file + " failed " + reason);
-        mResultRecorder.failed(file, reason);
-
-        String bugNumber = FileFilter.isKnownBug(file);
-        if (bugNumber != null) {
-            System.out.println("FAIL known:"+bugNumber+ " "+file+reason);
-            return;
-        }
-        if (FileFilter.ignoreResults(file)) {
-            return;
-        }
-        System.out.println("FAIL: "+file+reason);        
-    }
-
-    public void passedCase(String file) {
-        Log.v("Layout test:", file + " passed");
-        mResultRecorder.passed(file);
-
-        String bugNumber = FileFilter.isKnownBug(file);
-        if (bugNumber != null) {
-            System.out.println("Bug Fixed: "+bugNumber+ " "+file);
-            return;
-        }
- 
-        if (FileFilter.ignoreResults(file)) {
-            System.out.println("Ignored test passed: "+file);
-            return;
-        }
-    }
-
-    public void nontextCase(String file, boolean has_expected_results) {
-        Log.v("Layout test:", file + " nontext");
-        mResultRecorder.nontext(file, has_expected_results);
-    }
- 
-    public void setCallback(HTMLHostCallbackInterface callback) {
-        mCallback = callback;
-    }
-
-    public void processResult(boolean timeout, String test_path) {
-        Log.v(LOGTAG, "  Processing result: " + test_path);
-        // remove the extension
-        String short_file = test_path.substring(0, test_path.lastIndexOf('.'));
-        if (timeout) {
-            failedCase(test_path, "TIMEDOUT");
-            return;
-        }
-        // Only check results that we can check, ie dumpAsText results
-        String dumpFile = short_file + "-results.txt";
-        File f = new File(dumpFile);
-        if (f.exists()) {
-            try {
-                FileInputStream fr = new FileInputStream(short_file+"-results.txt");
-                FileInputStream fe = new FileInputStream(short_file+"-expected.txt");
-              
-                // If the length is different then they are different
-                int diff = fe.available() - fr.available();
-                if (diff > 1 || diff < 0) {
-                    failedCase(test_path, " different length");
-                    fr.close();
-                    fe.close();
-                    return;
-                }
-                byte[] br = new byte[fr.available()];
-                byte[] be = new byte[fe.available()];
-                fr.read(br);
-                fe.read(be);
-                boolean fail = false;
-                for (int i = 0; i < br.length; i++) {
-                    if (br[i] != be[i]) {
-                        failedCase(test_path, "  @offset: "+i);
-                        fr.close();
-                        fe.close();
-                        return;
-                    }
-                }
-                if (br.length != be.length && be[be.length-1] == '\n') {
-                    Log.d(LOGTAG, "Extra new line being ignore:" + test_path);
-                }
-                fr.close();
-                fe.close();
-                passedCase(test_path);
-            } catch (FileNotFoundException ex) {
-              // TODO do something here
-            } catch (IOException ex) {
-              // Failed on available() or read()
-            }
-            
-            return;
-        }
-        
-        File nontext_result = new File(short_file + "-android-results.txt");
-        if (nontext_result.exists()) {
-            // Check if the test has expected results.
-            File expected = new File(short_file + "-expected.txt");
-            nontextCase(test_path, expected.exists());
-        }
-    }
-    
-    public void finished() {
-        if (mCallback != null) {
-            mCallback.waitForFinish();
-        }
-
-        mFinishedRunning = true;
-        finish();
-    }
-    
-    // LayoutTestController Functions
-    public void dumpAsText() {
-        mDumpAsText = true;
-        if (mWebView != null) {
-            String url = mWebView.getUrl();
-            Log.v(LOGTAG, "dumpAsText called: "+url);
-        }
-    }
-
-    public void waitUntilDone() {
-        mWaitUntilDone = true;
-        String url = mWebView.getUrl();
-        Log.v(LOGTAG, "waitUntilDone called: " + url);
-    }
-    public void notifyDone() {
-        String url = mWebView.getUrl();
-        Log.v(LOGTAG, "notifyDone called: " + url);
-        if (mWaitUntilDone) {
-            mWaitUntilDone = false;
-            mChromeClient.onProgressChanged(mWebView, 100);
-        }
-    }
-    
-    public void display() {
-        mWebView.invalidate();
-    }
-
-    public void clearBackForwardList() {
-        mWebView.clearHistory();
-
-    }
-
-    public void dumpBackForwardList() {
-        //printf("\n============== Back Forward List ==============\n");
-        // mWebHistory
-        //printf("===============================================\n");
-
-    }
-
-    public void dumpChildFrameScrollPositions() {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void dumpEditingCallbacks() {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void dumpSelectionRect() {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void dumpTitleChanges() {
-        if (!mDumpTitleChanges) {
-            mTitleChanges = new StringBuffer();
-        }
-        mDumpTitleChanges = true;
-    }
-
-    public void keepWebHistory() {
-        if (!mKeepWebHistory) {
-            mWebHistory = new Vector();
-        }
-        mKeepWebHistory = true;
-    }
-
-    public void queueBackNavigation(int howfar) {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void queueForwardNavigation(int howfar) {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void queueLoad(String Url, String frameTarget) {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void queueReload() {
-        mWebView.reload();
-    }
-
-    public void queueScript(String scriptToRunInCurrentContext) {
-        mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext);     
-    }
-
-    public void repaintSweepHorizontally() {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void setAcceptsEditing(boolean b) {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void setMainFrameIsFirstResponder(boolean b) {
-        // TODO Auto-generated method stub
-
-    }
-
-    public void setWindowIsKey(boolean b) {
-        // This is meant to show/hide the window. The best I can find
-        // is setEnabled()
-        mWebView.setEnabled(b);
-    }
-
-    public void testRepaint() {
-        mWebView.invalidate();
-    }
-
-    // Instrumentation calls this to find
-    // if the activity has finished running the layout tests
-    // TODO(fqian): need to sync on mFinisheRunning
-    public boolean hasFinishedRunning() {
-        return mFinishedRunning;
-    }
-    
-    private final WebChromeClient mChromeClient = new WebChromeClient() {
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            if (newProgress == 100) {
-                if (!mSingleTestMode && !mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) {
-                    String url = mWebView.getUrl();
-                    Log.v(LOGTAG, "Finished: "+ url);
-                    mHandler.removeMessages(MSG_TIMEOUT);
-                    requestWebKitData();
-                } else {
-                    String url = mWebView.getUrl();
-                    if (mSingleTestMode) {
-                        Log.v(LOGTAG, "Single test mode: " + url);
-                    } else if (mTimedOut) {
-                        Log.v(LOGTAG, "Timed out before finishing: " + url);
-                    } else if (mWaitUntilDone) {
-                        Log.v(LOGTAG, "Waiting for notifyDone: " + url);
-                    } else if (mRequestedWebKitData) {
-                        Log.v(LOGTAG, "Requested webkit data ready: " + url);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void onReceivedTitle(WebView view, String title) {
-            if (title.length() > 30)
-                title = "..."+title.substring(title.length()-30);
-            setTitle(title);
-            if (mDumpTitleChanges) {
-                mTitleChanges.append("TITLE CHANGED: ");
-                mTitleChanges.append(title);
-                mTitleChanges.append("\n");
-            }
-        }
-
-        @Override
-        public boolean onJsAlert(WebView view, String url, String message,
-                JsResult result) {
-            if (mDialogStrings == null) {
-                mDialogStrings = new StringBuffer();
-            }
-            mDialogStrings.append("ALERT: ");
-            mDialogStrings.append(message);
-            mDialogStrings.append('\n');
-            result.confirm();
-            return true;
-        }
-        
-        @Override
-        public boolean onJsConfirm(WebView view, String url, String message,
-                JsResult result) {
-            if (mDialogStrings == null) {
-                mDialogStrings = new StringBuffer();
-            }
-            mDialogStrings.append("CONFIRM: ");
-            mDialogStrings.append(message);
-            mDialogStrings.append('\n');
-            result.confirm();
-            return true;
-        }
-        
-        @Override
-        public boolean onJsPrompt(WebView view, String url, String message,
-                String defaultValue, JsPromptResult result) {
-            if (mDialogStrings == null) {
-                mDialogStrings = new StringBuffer();
-            }
-            mDialogStrings.append("PROMPT: ");
-            mDialogStrings.append(message);
-            mDialogStrings.append(", default text: ");
-            mDialogStrings.append(defaultValue);
-            mDialogStrings.append('\n');
-            result.confirm();
-            return true;
-        }
-    };
-    
-    private void resetTestStatus() {
-        mWaitUntilDone = false;
-        mDumpAsText = false;
-        mTimedOut = false;
-        mDumpTitleChanges = false;
-        mRequestedWebKitData = false;
-        mEventSender.resetMouse();
-    }
-    
-    private TestRecorder mResultRecorder;
-    private HTMLHostCallbackInterface mCallback = null;
-    private CallbackProxy mCallbackProxy;
-    
-    private WebView mWebView;
-    private WebViewEventSender mEventSender;
-    
-    private Vector<String> mTestList;
-    private int mTestIndex;
-
-    private int mTimeoutInMillis;
-    private String mTestPathPrefix;
-    private boolean mSingleTestMode;
-    
-    private AsyncHandler mHandler;
-    private boolean mFinishedRunning;
-
-    private boolean mTimedOut;
-    private boolean mRequestedWebKitData;
-    private boolean mDumpAsText;
-    private boolean mWaitUntilDone;
-    private boolean mDumpTitleChanges;
-    
-    private StringBuffer mTitleChanges;
-    private StringBuffer mDialogStrings;
-
-    private boolean mKeepWebHistory;
-    private Vector mWebHistory;
-
-    static final String TIMEOUT_STR = "**Test timeout";
-    
-    static final int MSG_TIMEOUT = 0;
-    static final int MSG_WEBKIT_DATA = 1;
-
-    static final String LOGTAG="DumpRenderTree";
-
-    static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/";
-    static final String LAYOUT_TESTS_LIST_FILE = "/sdcard/layout_tests_list.txt";
-    static final String TEST_STATUS_FILE = "/sdcard/running_test.txt";
-    
-    static final String RESUME_FROM_CRASH = "ResumeFromCrash";
-    static final String TEST_PATH_PREFIX = "TestPathPrefix";
-    static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
-    static final String SINGLE_TEST_MODE = "SingleTestMode";
-}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index 1f37405..8f968b4 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -27,7 +27,7 @@
 
 
 /**
- * Instrumentation Test Runner for all MediaPlayer tests.
+ * Instrumentation Test Runner for all DumpRenderTree tests.
  * 
  * Running all tests:
  *
@@ -40,6 +40,7 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(LayoutTestsAutoTest.class);
+        suite.addTestSuite(LoadTestsAutoTest.class);
         return suite;
     }
 
@@ -51,18 +52,22 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        String path = (String) icicle.get("path");
-        LayoutTestsAutoTest.setLayoutTestDir(path);
+        this.mTestPath = (String) icicle.get("path");
         String timeout_str = (String) icicle.get("timeout");
-        int timeout = 0;  // default value
         if (timeout_str != null) {
             try {
-                timeout = Integer.parseInt(timeout_str);
+                this.mTimeoutInMillis = Integer.parseInt(timeout_str);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
-        LayoutTestsAutoTest.setTimeoutInMillis(timeout);
+        
+        String r = (String)icicle.get("rebaseline");
+        this.mRebaseline = (r != null && r.toLowerCase().equals("true"));
     }
+    
+    public String mTestPath = null;
+    public int mTimeoutInMillis = 0;
+    public boolean mRebaseline = false;
 }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 3e65f0358..a857e68 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -25,92 +25,375 @@
 
 import android.util.Log;
 import android.view.KeyEvent;
+import android.webkit.WebSettings;
 
 import android.os.Bundle;
 import android.os.Message;
-import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 
-import com.android.dumprendertree.HTMLHostActivity;
+import com.android.dumprendertree.TestShellActivity;
 
 import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
+import java.util.Vector;
 
-public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase<Menu> {
+//TestRecorder creates two files, one for passing tests
+//and another for failing tests and writes the paths to
+//layout tests one line at a time. TestRecorder does not
+//have ability to clear the results.
+class MyTestRecorder {
+    private BufferedOutputStream mBufferedOutputPassedStream;
+    private BufferedOutputStream mBufferedOutputFailedStream;
+    private BufferedOutputStream mBufferedOutputNoresultStream;
+    
+    public void passed(String layout_file) {
+        try {
+            mBufferedOutputPassedStream.write(layout_file.getBytes());
+            mBufferedOutputPassedStream.write('\n');
+            mBufferedOutputPassedStream.flush();
+        } catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public void failed(String layout_file) {
+        try {
+            mBufferedOutputFailedStream.write(layout_file.getBytes());
+            mBufferedOutputFailedStream.write('\n');
+            mBufferedOutputFailedStream.flush();
+        } catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public void noresult(String layout_file) {
+        try {
+            mBufferedOutputNoresultStream.write(layout_file.getBytes());
+            mBufferedOutputNoresultStream.write('\n');
+            mBufferedOutputNoresultStream.flush();
+        } catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public MyTestRecorder(boolean resume) {
+        try {
+            File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt");
+            File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt");
+            File noExpectedResultFile = new File("/sdcard/layout_tests_nontext.txt");
+          
+            mBufferedOutputPassedStream =
+                new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume));
+            mBufferedOutputFailedStream =
+                new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume));
+            mBufferedOutputNoresultStream =
+                new BufferedOutputStream(new FileOutputStream(noExpectedResultFile, resume));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public void close() {
+        try {
+            mBufferedOutputPassedStream.close();
+            mBufferedOutputFailedStream.close();
+            mBufferedOutputNoresultStream.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
 
-    private final static String LOGTAG = "LayoutTests";
-    private final static int DEFAULT_TIMEOUT_IN_MILLIS = 6000;
-    private static String layoutTestDir = null;
-    private static int mTimeoutInMillis = 0;
+
+public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {
+
+    private static final String LOGTAG = "LayoutTests";
+    static final int DEFAULT_TIMEOUT_IN_MILLIS = 5000;
+    
+    static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/";
+    static final String LAYOUT_TESTS_RESULT_DIR = "/sdcard/android/layout_tests_results/";
+    static final String ANDROID_EXPECTED_RESULT_DIR = "/sdcard/android/expected_results/";
+    static final String LAYOUT_TESTS_LIST_FILE = "/sdcard/android/layout_tests_list.txt";
+    static final String TEST_STATUS_FILE = "/sdcard/android/running_test.txt";
+
+    private MyTestRecorder mResultRecorder;
+    private Vector<String> mTestList;
+    private boolean mRebaselineResults;
+    private String mTestPathPrefix;
     
     public LayoutTestsAutoTest() {
-      super("com.android.dumprendertree", Menu.class);
+      super("com.android.dumprendertree", TestShellActivity.class);
     }
 
     // This function writes the result of the layout test to
     // Am status so that it can be picked up from a script.
-    public void passOrFailCallback(String file, boolean result) {
+    private void passOrFailCallback(String file, boolean result) {
       Instrumentation inst = getInstrumentation();
       Bundle bundle = new Bundle();
       bundle.putBoolean(file, result);
       inst.sendStatus(0, bundle);
     }
-
-    public static void setTimeoutInMillis(int millis) {
-        mTimeoutInMillis = (millis > 0) ? millis : DEFAULT_TIMEOUT_IN_MILLIS;
+    
+    private void getTestList() {
+        // Read test list.
+        try {
+            BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE));
+            String line = inReader.readLine();
+            while (line != null) {
+                if (line.startsWith(mTestPathPrefix))
+                    mTestList.add(line);
+                line = inReader.readLine();
+            }
+            inReader.close();
+            Log.v(LOGTAG, "Test list has " + mTestList.size() + " test(s).");
+        } catch (Exception e) {
+            Log.e(LOGTAG, "Error while reading test list : " + e.getMessage());
+        }
+    }
+  
+    private void resumeTestList() {
+        // read out the test name it stoped last time.
+        try {
+            BufferedReader inReader = new BufferedReader(new FileReader(TEST_STATUS_FILE));
+            String line = inReader.readLine();
+            for (int i = 0; i < mTestList.size(); i++) {
+                if (mTestList.elementAt(i).equals(line)) {
+                    mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size()));
+                    break;
+                }
+            }
+            inReader.close();
+        } catch (Exception e) {
+            Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE);
+        }
+    }
+  
+    private void clearTestStatus() {
+        // Delete TEST_STATUS_FILE
+        try {
+            File f = new File(TEST_STATUS_FILE);
+            if (f.delete())
+                Log.v(LOGTAG, "Deleted " + TEST_STATUS_FILE);
+            else
+                Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE);
+        } catch (Exception e) {
+            Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE + " : " + e.getMessage());
+        }
+    }
+  
+    private void updateTestStatus(String s) {
+        // Write TEST_STATUS_FILE
+        try {
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(TEST_STATUS_FILE));
+            bos.write(s.getBytes());
+            bos.close();
+        } catch (Exception e) {
+            Log.e(LOGTAG, "Cannot update file " + TEST_STATUS_FILE);
+        }
+    }
+    
+    private String getResultFile(String test) {
+        String shortName = test.substring(0, test.lastIndexOf('.'));
+        // Write actual results to result directory.
+        return shortName.replaceFirst(LAYOUT_TESTS_ROOT, LAYOUT_TESTS_RESULT_DIR) + "-result.txt";
+    }
+    
+    private String getExpectedResultFile(String test) {
+        String shortName = test.substring(0, test.lastIndexOf('.'));
+        return shortName + "-expected.txt";          
     }
 
-    public static void setLayoutTestDir(String name) {
-        if (name == null)
-            throw new AssertionError("Layout test directory cannot be null.");
-      layoutTestDir = HTMLHostActivity.LAYOUT_TESTS_ROOT + name;
-      Log.v("LayoutTestsAutoTest", " Only running the layout tests : " + layoutTestDir);
+    private String getAndroidExpectedResultFile(String expectedResultFile) {
+        return expectedResultFile.replaceFirst(LAYOUT_TESTS_ROOT, ANDROID_EXPECTED_RESULT_DIR);
     }
 
+    // Wrap up
+    private void failedCase(String file) {
+        Log.w("Layout test: ", file + " failed");
+        mResultRecorder.failed(file);    
+    }
+
+    private void passedCase(String file) {
+        Log.v("Layout test:", file + " passed");
+        mResultRecorder.passed(file);
+    }
+
+    private void noresultCase(String file) {
+        Log.v("Layout test:", file + " no expected result");
+        mResultRecorder.noresult(file);
+    }
+     
+    private void processResult(String testFile, String actualResultFile, String expectedResultFile) {
+        Log.v(LOGTAG, "  Processing result: " + testFile);
+
+        File actual = new File(actualResultFile);
+        File expected = new File(expectedResultFile);
+        if (actual.exists() && expected.exists()) {
+            try {
+                boolean passing = true;
+                BufferedReader fr = new BufferedReader(new FileReader(actual));
+                BufferedReader fe = new BufferedReader(new FileReader(expected));
+                while (true) {
+                    String s1 = fr.readLine();
+                    String s2 = fe.readLine();
+                    if (s1 == null && s2 == null)
+                        break; // both files are the same
+                    if (s1 == null || s2 == null || !s1.equals(s2)) {
+                        passing = false;
+                        break;
+                    }
+                }
+                
+                if (passing) {
+                    passedCase(testFile);
+                } else {
+                    failedCase(testFile);
+                }
+                
+                fe.close();
+                fr.close();
+            } catch (FileNotFoundException ex) {
+                Log.e(LOGTAG, "File not found : " + ex.getMessage());
+            } catch (IOException ex) {
+                Log.e(LOGTAG, "IO Error : " + ex.getMessage());
+            }
+            return;
+        }
+
+        if (!expected.exists()) {
+            noresultCase(testFile);
+        }
+    }
+    
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String test, int timeout) {
+        activity.setCallback(new TestShellCallback() {
+            public void finished() {
+                synchronized (LayoutTestsAutoTest.this) {
+                    LayoutTestsAutoTest.this.notifyAll();
+                }
+            }         
+        });
+
+        String resultFile = getResultFile(test);
+        if (mRebaselineResults) {
+            String expectedResultFile = getExpectedResultFile(test);
+            File f = new File(expectedResultFile);
+            if (f.exists()) {
+                return;  // don't run test and don't overwrite default tests.
+            }
+
+            resultFile = getAndroidExpectedResultFile(expectedResultFile);
+        }
+        
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setClass(activity, TestShellActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        intent.putExtra(TestShellActivity.TEST_URL, "file://" + test);
+        intent.putExtra(TestShellActivity.RESULT_FILE, resultFile);
+        intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
+        activity.startActivity(intent);
+      
+        // Wait until done.
+        synchronized (this) {
+            try {
+                this.wait();
+            } catch (InterruptedException e) { }
+        }
+        
+        if (!mRebaselineResults) {
+            String expectedResultFile = getExpectedResultFile(test);
+            File f = new File(expectedResultFile);
+            if (!f.exists()) {
+                expectedResultFile = getAndroidExpectedResultFile(expectedResultFile);
+            }
+            
+            processResult(test, resultFile, expectedResultFile);
+        }
+    } 
+    
     // Invokes running of layout tests
     // and waits till it has finished running.
     public void executeLayoutTests(boolean resume) {
-      Instrumentation inst = getInstrumentation();
+        LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
+        // A convenient method to be called by another activity.
+
+        if (runner.mTestPath == null) {
+            Log.e(LOGTAG, "No test specified");
+            return;
+        }
+
+        this.mTestList = new Vector<String>();
       
-      {
-          Activity activity = getActivity();
-          Intent intent = new Intent();
-          intent.setClass(activity, HTMLHostActivity.class);
-          intent.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, resume);
-          intent.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, false);
-          intent.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, layoutTestDir);
-          intent.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, mTimeoutInMillis);
-          activity.startActivity(intent);
-      }
-      
-      ActivityMonitor htmlHostActivityMonitor =
-          inst.addMonitor("com.android.dumprendertree.HTMLHostActivity", null, false);
+        // Read settings
+        try {
+            this.mTestPathPrefix =
+                (new File(LAYOUT_TESTS_ROOT + runner.mTestPath)).getCanonicalPath();
+        } catch (IOException e) {  
+            Log.e(LOGTAG, "Cannot find test path prefix: " + e.getMessage());
+            return;
+        }
+        
+        this.mRebaselineResults = runner.mRebaseline;
+        
+        int timeout = runner.mTimeoutInMillis;
+        if (timeout <= 0) {
+            timeout = DEFAULT_TIMEOUT_IN_MILLIS;
+        }
+          
+        this.mResultRecorder = new MyTestRecorder(resume);
+          
+        if (!resume)
+            clearTestStatus();
+          
+        getTestList();
+        if (resume)
+            resumeTestList();
 
-      HTMLHostActivity activity =
-          (HTMLHostActivity) htmlHostActivityMonitor.waitForActivity();
+        TestShellActivity activity = (TestShellActivity) getActivity();
 
-      while (!activity.hasFinishedRunning()) {
-          // Poll every 5 seconds to determine if the layout
-          // tests have finished running
-          try {Thread.sleep(5000); } catch(Exception e){}
-      }
+        // Run tests.
+        for (int i = 0; i < mTestList.size(); i++) {
+            String s = mTestList.elementAt(i);
+            updateTestStatus(s);
+            // Run tests
+            runTestAndWaitUntilDone(activity, s, runner.mTimeoutInMillis);
+        }
 
-      // Wait few more seconds so that results are
-      // flushed to the /sdcard
-      try {Thread.sleep(5000); } catch(Exception e){}
+        updateTestStatus("#DONE");
+        
+        activity.finish();
+    }
 
-      // Clean up the HTMLHostActivity activity
-      activity.finish();
+
+    private String getTestPath() {
+        LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
+
+        String test_path = LAYOUT_TESTS_ROOT;
+        if (runner.mTestPath != null) {
+            test_path += runner.mTestPath;
+        }
+        try {
+            test_path = new File(test_path).getCanonicalPath();
+        } catch (IOException e) {
+            Log.e("LayoutTestsAutoTest", "Cannot get cannonical path " + e.getMessage());
+        }
+        Log.v("LayoutTestsAutoTest", " Test path : " + test_path);
+        
+        return test_path;
     }
     
     public void generateTestList() {
         try {
-            File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE);
+            File tests_list = new File(LAYOUT_TESTS_LIST_FILE);
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tests_list, false));
-            findTestsRecursively(bos, layoutTestDir);
+            findTestsRecursively(bos, getTestPath());
             bos.flush();
             bos.close();
        } catch (Exception e) {
@@ -156,7 +439,7 @@
     // in chunks.
     public void startLayoutTests() {
         try {
-            File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE);
+            File tests_list = new File(LAYOUT_TESTS_LIST_FILE);
             if (!tests_list.exists())
               generateTestList();
         } catch (Exception e) {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
new file mode 100644
index 0000000..b064dbb
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dumprendertree;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.content.Intent;
+
+import android.util.Log;
+
+import android.os.Bundle;
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.android.dumprendertree.TestShellActivity;
+import com.android.dumprendertree.TestShellCallback;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+class StreamPipe extends Thread {
+    InputStream in;
+    OutputStream out;
+    
+    StreamPipe(InputStream in, OutputStream out) {
+        this.in = in;
+        this.out = out;
+    }
+    
+    public void run() {
+        try {
+            byte[] buf = new byte[1024];
+            int nofb = this.in.read(buf);
+            while (nofb != -1) {
+                this.out.write(buf, 0, nofb);
+                nofb = this.in.read(buf);
+            }          
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
+
+public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {
+
+    private final static String LOGTAG = "LoadTest";
+    private final static String LOAD_TEST_RESULT = "/sdcard/load_test_result.txt";
+    
+    public LoadTestsAutoTest() {
+        super("com.android.dumprendertree", TestShellActivity.class);
+    }
+
+    // This function writes the result of the layout test to
+    // Am status so that it can be picked up from a script.
+    public void passOrFailCallback(String file, boolean result) {
+        Instrumentation inst = getInstrumentation();
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(file, result);
+        inst.sendStatus(0, bundle);
+    }
+    
+    // Invokes running of layout tests
+    // and waits till it has finished running.
+    public void runTest() {
+        LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
+
+        if (runner.mTestPath == null) {
+            Log.e(LOGTAG, "No test specified");
+            return;
+        }
+        
+        TestShellActivity activity = (TestShellActivity) getActivity();
+
+        // Run tests
+        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
+
+        // TODO(fqian): let am instrumentation pass in the command line, currently
+        // am instrument does not allow spaces in the command.
+        runPostShellCommand("/system/bin/dumpsys meminfo");
+        
+        // Kill activity
+        activity.finish();
+    }
+
+    private void runPostShellCommand(String cmd) {
+        if (cmd == null || cmd.length() == 0)
+            return;
+        
+        try {
+            // Call dumpsys meminfo
+            Process proc = Runtime.getRuntime().exec(cmd);
+            // Append output to LOAD_TEST_RESULT
+            InputStream input = proc.getInputStream();
+            InputStream error = proc.getErrorStream();
+            FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true);
+
+            StreamPipe p_in = new StreamPipe(input, out);
+            StreamPipe p_err = new StreamPipe(error, System.err);
+            
+            p_in.start();
+            p_err.start();
+            
+            proc.waitFor();
+        } catch (IOException e) {
+            Log.e(LOGTAG, e.getMessage());
+        } catch (InterruptedException e) {
+            Log.e(LOGTAG, e.getMessage());
+        }      
+    }
+    
+    // A convenient method to be called by another activity.
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout) {
+        activity.setCallback(new TestShellCallback() {
+            public void finished() {
+                synchronized (LoadTestsAutoTest.this) {
+                    LoadTestsAutoTest.this.notifyAll();
+                }
+            }         
+        });
+        
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setClass(activity, TestShellActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        intent.putExtra(TestShellActivity.TEST_URL, url);
+        intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
+        intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT);
+        activity.startActivity(intent);
+        
+        // Wait until done.
+        synchronized (this) {
+            try {
+                this.wait();
+            } catch (InterruptedException e) { }
+        }
+    }   
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
index de0da61..00e0f89 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.util.Log;
 
 import java.io.File;
 
@@ -42,15 +43,12 @@
     }
     
     void processFile(String filename, boolean selection)
-    {
-        Intent result = new Intent();
-        result.setClass(this, HTMLHostActivity.class);
-        result.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, false);
-        result.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, true);
-        result.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, filename);
-        result.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, 8000);
-        startActivity(result);
+    {        
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setClass(this, TestShellActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        intent.putExtra(TestShellActivity.TEST_URL, "file://" + filename);
+        startActivity(intent);
     }
-   
 }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
new file mode 100644
index 0000000..bf8a3b3
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dumprendertree;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.util.Log;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.view.ViewGroup;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.widget.LinearLayout;
+import android.os.*;
+
+public class TestShellActivity extends Activity implements LayoutTestController {
+    public class AsyncHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_TIMEOUT) {
+                mTimedOut = true;
+                requestWebKitData();
+                return;
+            } else if (msg.what == MSG_WEBKIT_DATA) {
+                TestShellActivity.this.dump(mTimedOut, (String)msg.obj);
+                return;
+            }
+
+            super.handleMessage(msg);
+        }
+    }
+
+    public void requestWebKitData() {
+        Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA);
+        
+        if (mRequestedWebKitData)
+            throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl());
+        
+        mRequestedWebKitData = true;
+        if (mDumpAsText) { 
+            mWebView.documentAsText(callback);
+        } else {
+            mWebView.externalRepresentation(callback);
+        }
+    } 
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        LinearLayout contentView = new LinearLayout(this);
+        contentView.setOrientation(LinearLayout.VERTICAL);
+        setContentView(contentView);
+
+        mWebView = new WebView(this);
+        mWebView.getSettings().setJavaScriptEnabled(true);
+        mWebView.setWebChromeClient(mChromeClient);
+        mEventSender = new WebViewEventSender(mWebView);
+        mCallbackProxy = new CallbackProxy(mEventSender, this);
+
+        mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController");
+        mWebView.addJavascriptInterface(mCallbackProxy, "eventSender");
+        contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
+ 
+        mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
+            
+        mHandler = new AsyncHandler();
+        
+        Intent intent = getIntent();
+        if (intent != null) {
+            executeIntent(intent);
+        }
+    }
+    
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        executeIntent(intent);
+    }
+    
+    private void executeIntent(Intent intent) {
+        resetTestStatus();
+        if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
+            return;
+        }
+        
+        mTestUrl = intent.getStringExtra(TEST_URL);
+        if (mTestUrl == null)
+            return;
+        
+        mResultFile = intent.getStringExtra(RESULT_FILE);
+        mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
+
+        Log.v(LOGTAG, "  Loading " + mTestUrl);
+        mWebView.loadUrl(mTestUrl);
+            
+        if (mTimeoutInMillis > 0) {
+            // Create a timeout timer
+            Message m = mHandler.obtainMessage(MSG_TIMEOUT);
+            mHandler.sendMessageDelayed(m, mTimeoutInMillis);
+        }
+    }
+    
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mWebView.stopLoading();
+    }
+    
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mWebView.destroy();
+        mWebView = null;
+    }
+    
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        Log.e(LOGTAG, "Low memory, kill self");
+        System.exit(1);
+    }
+
+    // Dump the page
+    public void dump(boolean timeout, String webkitData) {
+        if (mResultFile == null || mResultFile.length() == 0) {
+            finished();
+            return;
+        }
+        
+        try {
+            File parentDir = new File(mResultFile).getParentFile();
+            if (!parentDir.exists()) {
+                parentDir.mkdirs();
+            }
+            
+            FileOutputStream os = new FileOutputStream(mResultFile);
+            if (timeout) {
+                Log.w("Layout test: Timeout", mResultFile);
+                os.write(TIMEOUT_STR.getBytes());
+                os.write('\n');
+            }
+            if (mDumpTitleChanges)
+                os.write(mTitleChanges.toString().getBytes());
+            if (mDialogStrings != null)
+                os.write(mDialogStrings.toString().getBytes());
+            mDialogStrings = null;
+            os.write(webkitData.getBytes());
+            os.flush();
+            os.close();
+        } catch (IOException ex) {
+            Log.e(LOGTAG, "Cannot write to " + mResultFile + ", " + ex.getMessage());          
+        }
+
+        finished();
+    }
+    
+    public void setCallback(TestShellCallback callback) {
+        mCallback = callback;
+    }
+    
+    public void finished() {
+        if (mCallback != null) {
+            mCallback.finished();
+        }
+    }
+   
+    // .......................................
+    // LayoutTestController Functions
+    public void dumpAsText() {
+        mDumpAsText = true;
+        if (mWebView != null) {
+            String url = mWebView.getUrl();
+            Log.v(LOGTAG, "dumpAsText called: "+url);
+        }
+    }
+
+    public void waitUntilDone() {
+        mWaitUntilDone = true;
+        String url = mWebView.getUrl();
+        Log.v(LOGTAG, "waitUntilDone called: " + url);
+    }
+    
+    public void notifyDone() {
+        String url = mWebView.getUrl();
+        Log.v(LOGTAG, "notifyDone called: " + url);
+        if (mWaitUntilDone) {
+            mWaitUntilDone = false;
+            mChromeClient.onProgressChanged(mWebView, 100);
+        }
+    }
+    
+    public void display() {
+        mWebView.invalidate();
+    }
+
+    public void clearBackForwardList() {
+        mWebView.clearHistory();
+
+    }
+
+    public void dumpBackForwardList() {
+        //printf("\n============== Back Forward List ==============\n");
+        // mWebHistory
+        //printf("===============================================\n");
+
+    }
+
+    public void dumpChildFrameScrollPositions() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void dumpEditingCallbacks() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void dumpSelectionRect() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void dumpTitleChanges() {
+        if (!mDumpTitleChanges) {
+            mTitleChanges = new StringBuffer();
+        }
+        mDumpTitleChanges = true;
+    }
+
+    public void keepWebHistory() {
+        if (!mKeepWebHistory) {
+            mWebHistory = new Vector();
+        }
+        mKeepWebHistory = true;
+    }
+
+    public void queueBackNavigation(int howfar) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void queueForwardNavigation(int howfar) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void queueLoad(String Url, String frameTarget) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void queueReload() {
+        mWebView.reload();
+    }
+
+    public void queueScript(String scriptToRunInCurrentContext) {
+        mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext);     
+    }
+
+    public void repaintSweepHorizontally() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setAcceptsEditing(boolean b) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setMainFrameIsFirstResponder(boolean b) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setWindowIsKey(boolean b) {
+        // This is meant to show/hide the window. The best I can find
+        // is setEnabled()
+        mWebView.setEnabled(b);
+    }
+
+    public void testRepaint() {
+        mWebView.invalidate();
+    }
+    
+    private final WebChromeClient mChromeClient = new WebChromeClient() {
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            if (newProgress == 100) {
+                if (!mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) {
+                    String url = mWebView.getUrl();
+                    Log.v(LOGTAG, "Finished: "+ url);
+                    mHandler.removeMessages(MSG_TIMEOUT);
+                    requestWebKitData();
+                } else {
+                    String url = mWebView.getUrl();
+                    if (mTimedOut) {
+                        Log.v(LOGTAG, "Timed out before finishing: " + url);
+                    } else if (mWaitUntilDone) {
+                        Log.v(LOGTAG, "Waiting for notifyDone: " + url);
+                    } else if (mRequestedWebKitData) {
+                        Log.v(LOGTAG, "Requested webkit data ready: " + url);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onReceivedTitle(WebView view, String title) {
+            if (title.length() > 30)
+                title = "..."+title.substring(title.length()-30);
+            setTitle(title);
+            if (mDumpTitleChanges) {
+                mTitleChanges.append("TITLE CHANGED: ");
+                mTitleChanges.append(title);
+                mTitleChanges.append("\n");
+            }
+        }
+
+        @Override
+        public boolean onJsAlert(WebView view, String url, String message,
+                JsResult result) {
+            if (mDialogStrings == null) {
+                mDialogStrings = new StringBuffer();
+            }
+            mDialogStrings.append("ALERT: ");
+            mDialogStrings.append(message);
+            mDialogStrings.append('\n');
+            result.confirm();
+            return true;
+        }
+        
+        @Override
+        public boolean onJsConfirm(WebView view, String url, String message,
+                JsResult result) {
+            if (mDialogStrings == null) {
+                mDialogStrings = new StringBuffer();
+            }
+            mDialogStrings.append("CONFIRM: ");
+            mDialogStrings.append(message);
+            mDialogStrings.append('\n');
+            result.confirm();
+            return true;
+        }
+        
+        @Override
+        public boolean onJsPrompt(WebView view, String url, String message,
+                String defaultValue, JsPromptResult result) {
+            if (mDialogStrings == null) {
+                mDialogStrings = new StringBuffer();
+            }
+            mDialogStrings.append("PROMPT: ");
+            mDialogStrings.append(message);
+            mDialogStrings.append(", default text: ");
+            mDialogStrings.append(defaultValue);
+            mDialogStrings.append('\n');
+            result.confirm();
+            return true;
+        }
+    };
+    
+    private void resetTestStatus() {
+        mWaitUntilDone = false;
+        mDumpAsText = false;
+        mTimedOut = false;
+        mDumpTitleChanges = false;
+        mRequestedWebKitData = false;
+        mEventSender.resetMouse();
+    }
+    
+    private WebView mWebView;
+    private WebViewEventSender mEventSender;
+    private AsyncHandler mHandler;
+    private TestShellCallback mCallback;
+
+    private CallbackProxy mCallbackProxy;
+        
+    private String mTestUrl;
+    private String mResultFile;
+    private int mTimeoutInMillis;
+
+    // States
+    private boolean mTimedOut;
+    private boolean mRequestedWebKitData;
+    private boolean mFinishedRunning;
+
+    // Layout test controller variables.
+    private boolean mDumpAsText;
+    private boolean mWaitUntilDone;
+    private boolean mDumpTitleChanges;
+    private StringBuffer mTitleChanges;
+    private StringBuffer mDialogStrings;
+    private boolean mKeepWebHistory;
+    private Vector mWebHistory;
+
+    static final String TIMEOUT_STR = "**Test timeout";
+    
+    static final int MSG_TIMEOUT = 0;
+    static final int MSG_WEBKIT_DATA = 1;
+
+    static final String LOGTAG="TestShell";
+    
+    static final String TEST_URL = "TestUrl";
+    static final String RESULT_FILE = "ResultFile";
+    static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
similarity index 89%
rename from tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java
rename to tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
index 60a2915..759c443 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
@@ -16,6 +16,6 @@
 
 package com.android.dumprendertree;
 
-public interface HTMLHostCallbackInterface {
-    public void waitForFinish();
+public interface TestShellCallback {
+    public void finished();
 }
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index e248763..fc658f5 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -610,6 +610,62 @@
 }
 
 // ==========================================================
+static string
+generate_outputFileName(const Options& options, const document_item_type* items)
+{
+    string result;
+
+    // items has already been checked to have only one interface.
+    if (items->item_type == INTERFACE_TYPE) {
+        interface_type* type = (interface_type*)items;
+
+        // create the path to the destination folder based on the
+        // interface package name
+        result = options.outputBaseFolder;
+        result += OS_PATH_SEPARATOR;
+
+        string package = type->package;
+        size_t len = package.length();
+        for (size_t i=0; i<len; i++) {
+            if (package[i] == '.') {
+                package[i] = OS_PATH_SEPARATOR;
+            }
+        }
+
+        result += package;
+        
+        // add the filename by replacing the .aidl extension to .java
+        const char* p = strchr(type->name.data, '.');
+        len = p ? p-type->name.data : strlen(type->name.data);
+
+        result += OS_PATH_SEPARATOR;
+        result.append(type->name.data, len);
+        result += ".java";
+    }
+
+    return result;
+}
+
+// ==========================================================
+static void
+check_outputFileName(const string& path) {
+    size_t len = path.length();
+    for (size_t i=0; i<len ; i++) {
+        if (path[i] == OS_PATH_SEPARATOR) {
+            string p = path.substr(0, i);
+            if (access(path.data(), F_OK) != 0) {
+#ifdef HAVE_MS_C_RUNTIME
+                _mkdir(p.data());
+#else
+                mkdir(p.data(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
+#endif
+            }
+        }
+    }
+}
+
+
+// ==========================================================
 static int
 parse_preprocessed_file(const string& filename)
 {
@@ -804,7 +860,17 @@
         generate_dep_file(options);
     }
 
-    err = generate_java(options.outputFileName, options.inputFileName.c_str(),
+    // if needed, generate the outputFileName from the outputBaseFolder
+    string outputFileName = options.outputFileName;
+    if (outputFileName.length() == 0 &&
+            options.outputBaseFolder.length() > 0) {
+        outputFileName = generate_outputFileName(options, mainDoc);
+    }
+    
+    // make sure the folders of the output file all exists
+    check_outputFileName(outputFileName);
+
+    err = generate_java(outputFileName, options.inputFileName.c_str(),
                         (interface_type*)mainDoc);
 
     return err;
diff --git a/tools/aidl/options.cpp b/tools/aidl/options.cpp
index 57b10ae..0aa7db2 100644
--- a/tools/aidl/options.cpp
+++ b/tools/aidl/options.cpp
@@ -13,16 +13,19 @@
             "       aidl --preprocess OUTPUT INPUT...\n"
             "\n"
             "OPTIONS:\n"
-            "   -I<DIR>  search path for import statements.\n"
-            "   -d<FILE> generate dependency file.\n"
-            "   -p<FILE> file created by --preprocess to import.\n"
-            "   -b       fail when trying to compile a parcelable.\n"
+            "   -I<DIR>    search path for import statements.\n"
+            "   -d<FILE>   generate dependency file.\n"
+            "   -p<FILE>   file created by --preprocess to import.\n"
+            "   -o<FOLDER> base output folder for generated files.\n"
+            "   -b         fail when trying to compile a parcelable.\n"
             "\n"
             "INPUT:\n"
             "   An aidl interface file.\n"
             "\n"
             "OUTPUT:\n"
-            "   The generated interface files. If omitted, the input filename is used, with the .aidl extension changed to a .java extension.\n"
+            "   The generated interface files.\n"
+            "   If omitted and the -o option is not used, the input filename is used, with the .aidl extension changed to a .java extension.\n"
+            "   If the -o option is used, the generated files will be placed in the base output folder, under their package folder\n"
            );
     return 1;
 }
@@ -78,6 +81,14 @@
                         return usage();
                     }
                 }
+                else if (s[1] == 'o') {
+                    if (len > 2) {
+                        options->outputBaseFolder = s+2;
+                    } else {
+                        fprintf(stderr, "-o option (%d) requires a path.\n", i);
+                        return usage();
+                    }
+                }
                 else if (len == 2 && s[1] == 'b') {
                     options->failOnParcelable = true;
                 }
@@ -111,7 +122,7 @@
     if (i < argc) {
         options->outputFileName = argv[i];
         i++;
-    } else {
+    } else if (options->outputBaseFolder.length() == 0) {
         // copy input into output and change the extension from .aidl to .java
         options->outputFileName = options->inputFileName;
         string::size_type pos = options->outputFileName.size()-5;
diff --git a/tools/aidl/options.h b/tools/aidl/options.h
index dc3c45a..e9bf0f7 100644
--- a/tools/aidl/options.h
+++ b/tools/aidl/options.h
@@ -20,6 +20,7 @@
     vector<string> preprocessedFiles;
     string inputFileName;
     string outputFileName;
+    string outputBaseFolder;
     string depFileName;
 
     vector<string> filesToPreprocess;