Merge "Always splice historical data stats, debug info."
diff --git a/api/current.txt b/api/current.txt
index 9a53c56..40b63b1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5770,6 +5770,7 @@
     ctor public SyncAdapterType(android.os.Parcel);
     method public boolean allowParallelSyncs();
     method public int describeContents();
+    method public java.lang.String getSettingsActivity();
     method public boolean isAlwaysSyncable();
     method public boolean isUserVisible();
     method public static android.content.SyncAdapterType newKey(java.lang.String, java.lang.String);
@@ -16672,20 +16673,25 @@
   }
 
   public static final class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
     field public static final android.net.Uri CONTENT_LIMIT_URI;
     field public static final android.net.Uri CONTENT_PHOTO_URI;
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String MAX_ITEMS = "max_items";
   }
 
   public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
     field public static final java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
   }
 
   protected static abstract interface ContactsContract.StreamItemsColumns {
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
     field public static final java.lang.String COMMENTS = "comments";
+    field public static final java.lang.String CONTACT_ID = "contact_id";
     field public static final java.lang.String DATA_SET = "data_set";
     field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
     field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
@@ -24492,6 +24498,7 @@
     method public android.content.ComponentName getComponent();
     method public java.lang.String getId();
     method public java.lang.String getPackageName();
+    method public android.content.pm.ServiceInfo getServiceInfo();
     method public java.lang.String getSettingsActivity();
     method public android.view.textservice.SpellCheckerSubtype getSubtypeAt(int);
     method public int getSubtypeCount();
@@ -24517,6 +24524,7 @@
   public final class SpellCheckerSubtype implements android.os.Parcelable {
     ctor public SpellCheckerSubtype(int, java.lang.String, java.lang.String);
     method public int describeContents();
+    method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
     method public java.lang.String getExtraValue();
     method public java.lang.String getLocale();
     method public int getNameResId();
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index ee91c29..aa3bc03 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "stream"
+#include "utils/Log.h"
+
 #include <binder/ProcessState.h>
 
 #include <media/IStreamSource.h>
@@ -50,7 +54,7 @@
 private:
     int mFd;
     off64_t mFileSize;
-    int64_t mNextSeekTimeUs;
+    uint64_t mNumPacketsSent;
 
     sp<IStreamListener> mListener;
     Vector<sp<IMemory> > mBuffers;
@@ -61,7 +65,7 @@
 MyStreamSource::MyStreamSource(int fd)
     : mFd(fd),
       mFileSize(0),
-      mNextSeekTimeUs(-1) {  // ALooper::GetNowUs() + 5000000ll) {
+      mNumPacketsSent(0) {
     CHECK_GE(fd, 0);
 
     mFileSize = lseek64(fd, 0, SEEK_END);
@@ -84,18 +88,24 @@
 void MyStreamSource::onBufferAvailable(size_t index) {
     CHECK_LT(index, mBuffers.size());
 
-    if (mNextSeekTimeUs >= 0 && mNextSeekTimeUs <= ALooper::GetNowUs()) {
-        off64_t offset = (off64_t)(((float)rand() / RAND_MAX) * mFileSize * 0.8);
-        offset = (offset / 188) * 188;
+#if 0
+    if (mNumPacketsSent >= 20000) {
+        LOGI("signalling discontinuity now");
+
+        off64_t offset = 0;
+        CHECK((offset % 188) == 0);
 
         lseek(mFd, offset, SEEK_SET);
 
-        mListener->issueCommand(
-                IStreamListener::DISCONTINUITY, false /* synchronous */);
+        sp<AMessage> extra = new AMessage;
+        extra->setInt32(IStreamListener::kKeyFormatChange, 0);
 
-        mNextSeekTimeUs = -1;
-        mNextSeekTimeUs = ALooper::GetNowUs() + 5000000ll;
+        mListener->issueCommand(
+                IStreamListener::DISCONTINUITY, false /* synchronous */, extra);
+
+        mNumPacketsSent = 0;
     }
+#endif
 
     sp<IMemory> mem = mBuffers.itemAt(index);
 
@@ -104,6 +114,8 @@
         mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
     } else {
         mListener->queueBuffer(index, n);
+
+        mNumPacketsSent += n / 188;
     }
 }
 ////////////////////////////////////////////////////////////////////////////////
@@ -293,12 +305,17 @@
     sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
     CHECK_EQ(composerClient->initCheck(), (status_t)OK);
 
+    ssize_t displayWidth = composerClient->getDisplayWidth(0);
+    ssize_t displayHeight = composerClient->getDisplayHeight(0);
+
+    LOGV("display is %d x %d\n", displayWidth, displayHeight);
+
     sp<SurfaceControl> control =
         composerClient->createSurface(
                 String8("A Surface"),
                 0,
-                1280,
-                800,
+                displayWidth,
+                displayHeight,
                 PIXEL_FORMAT_RGB_565,
                 0);
 
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index fcc19a2..6bffed7 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -34,6 +34,51 @@
  * If a cancelSync() is received that matches an existing sync operation then the thread
  * that is running that sync operation will be interrupted, which will indicate to the thread
  * that the sync has been canceled.
+ * <p>
+ * In order to be a sync adapter one must extend this class, provide implementations for the
+ * abstract methods and write a service that returns the result of {@link #getSyncAdapterBinder()}
+ * in the service's {@link android.app.Service#onBind(android.content.Intent)} when invoked
+ * with an intent with action <code>android.content.SyncAdapter</code>. This service
+ * must specify the following intent filter and metadata tags in its AndroidManifest.xml file
+ * <pre>
+ *   &lt;intent-filter&gt;
+ *     &lt;action android:name="android.content.SyncAdapter" /&gt;
+ *   &lt;/intent-filter&gt;
+ *   &lt;meta-data android:name="android.content.SyncAdapter"
+ *             android:resource="@xml/syncadapter" /&gt;
+ * </pre>
+ * The <code>android:resource</code> attribute must point to a resource that looks like:
+ * <pre>
+ * &lt;sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
+ *    android:contentAuthority="authority"
+ *    android:accountType="accountType"
+ *    android:userVisible="true|false"
+ *    android:supportsUploading="true|false"
+ *    android:allowParallelSyncs="true|false"
+ *    android:isAlwaysSyncable="true|false"
+ *    android:syncAdapterSettingsAction="ACTION_OF_SETTINGS_ACTIVITY"
+ * /&gt;
+ * </pre>
+ * <ul>
+ * <li>The <code>android:contentAuthority</code> and <code>android:accountType</code> attributes
+ * indicate which content authority and for which account types this sync adapter serves.
+ * <li><code>android:userVisible</code> defaults to true and controls whether or not this sync
+ * adapter shows up in the Sync Settings screen.
+ * <li><code>android:supportsUploading</code> defaults
+ * to true and if true an upload-only sync will be requested for all syncadapters associated
+ * with an authority whenever that authority's content provider does a
+ * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}
+ * with syncToNetwork set to true.
+ * <li><code>android:allowParallelSyncs</code> defaults to false and if true indicates that
+ * the sync adapter can handle syncs for multiple accounts at the same time. Otherwise
+ * the SyncManager will wait until the sync adapter is not in use before requesting that
+ * it sync an account's data.
+ * <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager
+ * to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
+ * <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it
+ * specifies an Intent action of an activity that can be used to adjust the sync adapter's
+ * sync settings. The activity must live in the same package as the sync adapter.
+ * </ul>
  */
 public abstract class AbstractThreadedSyncAdapter {
     /**
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index b85346e..8a16ac9 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -32,6 +32,7 @@
     private final boolean supportsUploading;
     private final boolean isAlwaysSyncable;
     private final boolean allowParallelSyncs;
+    private final String settingsActivity;
 
     public SyncAdapterType(String authority, String accountType, boolean userVisible,
             boolean supportsUploading) {
@@ -47,6 +48,7 @@
         this.supportsUploading = supportsUploading;
         this.isAlwaysSyncable = false;
         this.allowParallelSyncs = false;
+        this.settingsActivity = null;
         this.isKey = false;
     }
 
@@ -54,7 +56,8 @@
     public SyncAdapterType(String authority, String accountType, boolean userVisible,
             boolean supportsUploading,
             boolean isAlwaysSyncable,
-            boolean allowParallelSyncs) {
+            boolean allowParallelSyncs,
+            String settingsActivity) {
         if (TextUtils.isEmpty(authority)) {
             throw new IllegalArgumentException("the authority must not be empty: " + authority);
         }
@@ -67,6 +70,7 @@
         this.supportsUploading = supportsUploading;
         this.isAlwaysSyncable = isAlwaysSyncable;
         this.allowParallelSyncs = allowParallelSyncs;
+        this.settingsActivity = settingsActivity;
         this.isKey = false;
     }
 
@@ -83,6 +87,7 @@
         this.supportsUploading = true;
         this.isAlwaysSyncable = false;
         this.allowParallelSyncs = false;
+        this.settingsActivity = null;
         this.isKey = true;
     }
 
@@ -131,6 +136,18 @@
         return isAlwaysSyncable;
     }
 
+    /**
+     * @return The activity to use to invoke this SyncAdapter's settings activity.
+     * May be null.
+     */
+    public String getSettingsActivity() {
+        if (isKey) {
+            throw new IllegalStateException(
+                    "this method is not allowed to be called when this is a key");
+        }
+        return settingsActivity;
+    }
+
     public static SyncAdapterType newKey(String authority, String accountType) {
         return new SyncAdapterType(authority, accountType);
     }
@@ -163,6 +180,7 @@
                     + ", supportsUploading=" + supportsUploading
                     + ", isAlwaysSyncable=" + isAlwaysSyncable
                     + ", allowParallelSyncs=" + allowParallelSyncs
+                    + ", settingsActivity=" + settingsActivity
                     + "}";
         }
     }
@@ -182,6 +200,7 @@
         dest.writeInt(supportsUploading ? 1 : 0);
         dest.writeInt(isAlwaysSyncable ? 1 : 0);
         dest.writeInt(allowParallelSyncs ? 1 : 0);
+        dest.writeString(settingsActivity);
     }
 
     public SyncAdapterType(Parcel source) {
@@ -191,7 +210,8 @@
                 source.readInt() != 0,
                 source.readInt() != 0,
                 source.readInt() != 0,
-                source.readInt() != 0);
+                source.readInt() != 0,
+                source.readString());
     }
 
     public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index 33a713b..7b643a0 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -66,8 +66,11 @@
             final boolean allowParallelSyncs =
                     sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_allowParallelSyncs,
                             false);
+            final String settingsActivity =
+                    sa.getString(com.android.internal.R.styleable
+                            .SyncAdapter_settingsActivity);
             return new SyncAdapterType(authority, accountType, userVisible, supportsUploading,
-		    isAlwaysSyncable, allowParallelSyncs);
+                    isAlwaysSyncable, allowParallelSyncs, settingsActivity);
         } finally {
             sa.recycle();
         }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index a00f790..5c3a17a 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -345,7 +345,6 @@
             sb.append(" (no locale)");
         }
         switch (textLayoutDirection) {
-            case LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
             case LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
             default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
         }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 55f3b4a..e9221fe 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3024,6 +3024,16 @@
                 Uri.withAppendedPath(AUTHORITY_URI, "stream_items_limit");
 
         /**
+         * The MIME type of a directory of stream items.
+         */
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
+
+        /**
+         * The MIME type of a single stream item.
+         */
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
+
+        /**
          * Queries to {@link ContactsContract.StreamItems#CONTENT_LIMIT_URI} will
          * contain this column, with the value indicating the maximum number of
          * stream items that will be stored under any single raw contact.
@@ -3050,6 +3060,17 @@
              * The directory twig for this sub-table
              */
             public static final String CONTENT_DIRECTORY = "photo";
+
+            /**
+             * The MIME type of a directory of stream item photos.
+             */
+            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
+
+            /**
+             * The MIME type of a single stream item photo.
+             */
+            public static final String CONTENT_ITEM_TYPE
+                    = "vnd.android.cursor.item/stream_item_photo";
         }
     }
 
@@ -3060,6 +3081,12 @@
      */
     protected interface StreamItemsColumns {
         /**
+         * A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
+         * that this stream item belongs to.
+         */
+        public static final String CONTACT_ID = "contact_id";
+
+        /**
          * A reference to the {@link RawContacts#_ID}
          * that this stream item belongs to.
          */
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 6debc6b..18b4040 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -17,6 +17,10 @@
 package android.text;
 
 
+import java.util.Locale;
+
+import android.util.LocaleUtil;
+
 /**
  * Some objects that implement TextDirectionHeuristic.
  * @hide
@@ -75,6 +79,11 @@
     public static final TextDirectionHeuristic CHARCOUNT_RTL =
         new TextDirectionHeuristicInternal(CharCount.INSTANCE_DEFAULT, true);
 
+    /**
+     * Force the paragraph direction to the Locale direction. Falls back to left to right.
+     */
+    public static final TextDirectionHeuristic LOCALE = TextDirectionHeuristicLocale.INSTANCE;
+
     private static enum TriState {
         TRUE, FALSE, UNKNOWN;
     }
@@ -300,4 +309,23 @@
         public static final float DEFAULT_THRESHOLD = 0.6f;
         public static final CharCount INSTANCE_DEFAULT = new CharCount(DEFAULT_THRESHOLD);
     }
+
+    /**
+     * Algorithm that uses the Locale direction to force the direction of a paragraph.
+     */
+    public static class TextDirectionHeuristicLocale extends TextDirectionHeuristicImpl {
+
+        public TextDirectionHeuristicLocale() {
+            super(null);
+        }
+
+        @Override
+        protected boolean defaultIsRtl() {
+            final int dir = LocaleUtil.getLayoutDirectionFromLocale(java.util.Locale.getDefault());
+            return (dir == LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE);
+        }
+
+        public static final TextDirectionHeuristicLocale INSTANCE =
+                new TextDirectionHeuristicLocale();
+    }
 }
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 74a930f..763af73 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -32,11 +32,6 @@
     /**
      * @hide Do not use. Implementation not finished.
      */
-    public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
-
-    /**
-     * @hide Do not use. Implementation not finished.
-     */
     public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0;
 
     /**
@@ -54,7 +49,6 @@
      *
      * @param locale the Locale for which we want the layout direction. Can be null.
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -63,17 +57,16 @@
      * @hide
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale == null || locale.equals(Locale.ROOT)) {
-            return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+        if (locale != null && !locale.equals(Locale.ROOT)) {
+            final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
+            if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
+
+            if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
+                    scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
+                return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+            }
         }
 
-        final String scriptSubtag = ICU.getScript(ICU.addLikelySubtags(locale.toString()));
-        if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
-
-        if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
-                scriptSubtag.equalsIgnoreCase(HEBR_SCRIPT_SUBTAG)) {
-            return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
-        }
         return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
     }
 
@@ -84,7 +77,6 @@
      *
      * @param locale
      * @return the layout direction. This may be one of:
-     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
      * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
@@ -94,13 +86,13 @@
      */
     private static int getLayoutDirectionFromFirstChar(Locale locale) {
         switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
-            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
                 return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
+
+            case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
             default:
-                return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
+                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
         }
     }
 }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index cfbb47c..c934c7b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -541,9 +541,19 @@
     
     @Override
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
-        return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+        if (bounds != null) {
+            return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+        }
+
+        int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
+        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+        int count = nSaveLayer(mRenderer, nativePaint, saveFlags);
+        if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
+        return count;
     }
 
+    private static native int nSaveLayer(int renderer, int paint, int saveFlags);    
+
     @Override
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
@@ -562,10 +572,15 @@
 
     @Override
     public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
-        return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
-                alpha, saveFlags);
+        if (bounds != null) {
+            return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+                    alpha, saveFlags);
+        }
+        return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
     }
 
+    private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);    
+
     @Override
     public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
             int saveFlags) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 926d424..2bf16d8 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -413,8 +413,8 @@
                 if (error != EGL_SUCCESS) {
                     // something bad has happened revert to
                     // normal rendering.
-                    fallback(error != EGL11.EGL_CONTEXT_LOST);
                     Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
+                    fallback(error != EGL11.EGL_CONTEXT_LOST);
                 }
             }
         }
@@ -702,8 +702,9 @@
 
         @Override
         void setup(int width, int height) {
-            checkCurrent();
-            mCanvas.setViewport(width, height);
+            if (validate()) {
+                mCanvas.setViewport(width, height);
+            }
         }
 
         boolean canDraw() {
@@ -810,9 +811,9 @@
             if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
                     !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
                 if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                    fallback(true);
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
                             GLUtils.getEGLErrorString(sEgl.eglGetError()));
+                    fallback(true);
                     return SURFACE_STATE_ERROR;
                 } else {
                     return SURFACE_STATE_UPDATED;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e97d88f..80b5dad 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9992,8 +9992,6 @@
                 // The dirty rect should always be null for a display list
                 canvas.onPreDraw(null);
 
-                final int restoreCount = canvas.save();
-
                 computeScroll();
                 canvas.translate(-mScrollX, -mScrollY);
                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
@@ -10005,8 +10003,6 @@
                 } else {
                     draw(canvas);
                 }
-
-                canvas.restoreToCount(restoreCount);
             } finally {
                 canvas.onPostDraw();
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6ea863f..a0cc287 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1352,7 +1352,7 @@
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
-                if (!hwInitialized) {
+                if (!hwInitialized && mAttachInfo.mHardwareRenderer.isEnabled()) {
                     mAttachInfo.mHardwareRenderer.invalidate(mHolder);
                 }
             }
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 89cb11c..9d8475d 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
@@ -71,7 +70,6 @@
         final PackageManager pm = context.getPackageManager();
         int label = 0;
         String settingsActivityComponent = null;
-        int isDefaultResId = 0;
 
         XmlResourceParser parser = null;
         try {
@@ -221,6 +219,15 @@
         return mService.loadIcon(pm);
     }
 
+
+    /**
+     * Return the raw information about the Service implementing this
+     * spell checker.  Do not modify the returned object.
+     */
+    public ServiceInfo getServiceInfo() {
+        return mService.serviceInfo;
+    }
+
     /**
      * Return the class name of an activity that provides a settings UI.
      * You can launch this activity be starting it with
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index dbd3081..aeb3ba6 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -17,13 +17,16 @@
 package android.view.textservice;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * This class is used to specify meta information of a subtype contained in a spell checker.
@@ -97,6 +100,48 @@
         return false;
     }
 
+    private static Locale constructLocaleFromString(String localeStr) {
+        if (TextUtils.isEmpty(localeStr))
+            return null;
+        String[] localeParams = localeStr.split("_", 3);
+        // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+        // because localeStr is not empty.
+        if (localeParams.length == 1) {
+            return new Locale(localeParams[0]);
+        } else if (localeParams.length == 2) {
+            return new Locale(localeParams[0], localeParams[1]);
+        } else if (localeParams.length == 3) {
+            return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+        }
+        return null;
+    }
+
+    /**
+     * @param context Context will be used for getting Locale and PackageManager.
+     * @param packageName The package name of the spell checker
+     * @param appInfo The application info of the spell checker
+     * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
+     * can have only one %s in it. If there is, the %s part will be replaced with the locale's
+     * display name by the formatter. If there is not, this method simply returns the string
+     * specified by mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the
+     * framework to generate an appropriate display name.
+     */
+    public CharSequence getDisplayName(
+            Context context, String packageName, ApplicationInfo appInfo) {
+        final Locale locale = constructLocaleFromString(mSubtypeLocale);
+        final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
+        if (mSubtypeNameResId == 0) {
+            return localeStr;
+        }
+        final CharSequence subtypeName = context.getPackageManager().getText(
+                packageName, mSubtypeNameResId, appInfo);
+        if (!TextUtils.isEmpty(subtypeName)) {
+            return String.format(subtypeName.toString(), localeStr);
+        } else {
+            return localeStr;
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 5dca348..c85b2d9 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -72,27 +72,53 @@
      * languages in settings will be returned.
      * @return the spell checker session of the spell checker
      */
-    // TODO: Add a method to get enabled spell checkers.
-    // TODO: Handle referToSpellCheckerLanguageSettings
     public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
             SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
         if (listener == null) {
             throw new NullPointerException();
         }
-        // TODO: set a proper locale instead of the dummy locale
-        final String localeString = locale == null ? "en" : locale.toString();
+        if (!referToSpellCheckerLanguageSettings && locale == null) {
+            throw new IllegalArgumentException("Locale should not be null if you don't refer"
+                    + " settings.");
+        }
         final SpellCheckerInfo sci;
         try {
-            sci = sService.getCurrentSpellChecker(localeString);
+            sci = sService.getCurrentSpellChecker(null);
         } catch (RemoteException e) {
             return null;
         }
         if (sci == null) {
             return null;
         }
+        SpellCheckerSubtype subtypeInUse = null;
+        if (referToSpellCheckerLanguageSettings) {
+            subtypeInUse = getCurrentSpellCheckerSubtype(true);
+            if (subtypeInUse == null) {
+                return null;
+            }
+            if (locale != null) {
+                final String subtypeLocale = subtypeInUse.getLocale();
+                final String inputLocale = locale.toString();
+                if (subtypeLocale.length() < 2 || inputLocale.length() < 2
+                        || !subtypeLocale.substring(0, 2).equals(inputLocale.substring(0, 2))) {
+                    return null;
+                }
+            }
+        } else {
+            final String localeStr = locale.toString();
+            for (int i = 0; i < sci.getSubtypeCount(); ++i) {
+                final SpellCheckerSubtype subtype = sci.getSubtypeAt(i);
+                if (subtype.getLocale().equals(localeStr)) {
+                    subtypeInUse = subtype;
+                }
+            }
+        }
+        if (subtypeInUse == null) {
+            return null;
+        }
         final SpellCheckerSession session = new SpellCheckerSession(sci, sService, listener);
         try {
-            sService.getSpellCheckerService(sci.getId(), localeString,
+            sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
                     session.getTextServicesSessionListener(),
                     session.getSpellCheckerSessionListener(), bundle);
         } catch (RemoteException e) {
@@ -146,10 +172,11 @@
     /**
      * @hide
      */
-    public SpellCheckerSubtype getCurrentSpellCheckerSubtype() {
+    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            boolean allowImplicitlySelectedSubtype) {
         try {
             // Passing null as a locale for ICS
-            return sService.getCurrentSpellCheckerSubtype(null);
+            return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e);
             return null;
@@ -161,10 +188,13 @@
      */
     public void setSpellCheckerSubtype(SpellCheckerSubtype subtype) {
         try {
+            final int hashCode;
             if (subtype == null) {
-                throw new NullPointerException("SpellCheckerSubtype is null.");
+                hashCode = 0;
+            } else {
+                hashCode = subtype.hashCode();
             }
-            sService.setCurrentSpellCheckerSubtype(null, subtype.hashCode());
+            sService.setCurrentSpellCheckerSubtype(null, hashCode);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in setSpellCheckerSubtype:" + e);
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5d776fd..6238b72 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -43,6 +43,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.graphics.RegionIterator;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.net.Proxy;
@@ -605,8 +606,9 @@
     // know to handle Shift and arrows natively first
     private boolean mAccessibilityScriptInjected;
 
+    static final boolean USE_WEBKIT_RINGS = true;
     // the color used to highlight the touch rectangles
-    private static final int mHightlightColor = 0x33000000;
+    private static final int mHightlightColor = 0x6633b5e5;
     // the round corner for the highlight path
     private static final float TOUCH_HIGHLIGHT_ARC = 5.0f;
     // the region indicating where the user touched on the screen
@@ -619,6 +621,7 @@
     private Paint mTouchCrossHairColor;
     private int mTouchHighlightX;
     private int mTouchHighlightY;
+    private long mTouchHighlightRequested;
 
     // Basically this proxy is used to tell the Video to update layer tree at
     // SetBaseLayer time and to pause when WebView paused.
@@ -3451,6 +3454,7 @@
                 }
                 abortAnimation();
                 mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
+                nativeSetIsScrolling(false);
                 if (!mBlockWebkitViewMessages) {
                     WebViewCore.resumePriority();
                     if (!mSelectingText) {
@@ -3991,7 +3995,7 @@
         return super.drawChild(canvas, child, drawingTime);
     }
 
-    private void drawContent(Canvas canvas) {
+    private void drawContent(Canvas canvas, boolean drawRings) {
         // Update the buttons in the picture, so when we draw the picture
         // to the screen, they are in the correct state.
         // Tell the native side if user is a) touching the screen,
@@ -4003,7 +4007,8 @@
         nativeRecordButtons(hasFocus() && hasWindowFocus(),
                             mTouchMode == TOUCH_SHORTPRESS_START_MODE
                             || mTrackballDown || mGotCenterDown, false);
-        drawCoreAndCursorRing(canvas, mBackgroundColor, mDrawCursorRing);
+        drawCoreAndCursorRing(canvas, mBackgroundColor,
+                mDrawCursorRing && drawRings);
     }
 
     /**
@@ -4067,7 +4072,15 @@
         if (mTitleBar != null) {
             canvas.translate(0, getTitleHeight());
         }
-        drawContent(canvas);
+        boolean drawJavaRings = !mTouchHighlightRegion.isEmpty()
+                && (mTouchMode == TOUCH_INIT_MODE
+                || mTouchMode == TOUCH_SHORTPRESS_START_MODE
+                || mTouchMode == TOUCH_SHORTPRESS_MODE);
+        boolean drawNativeRings = !drawJavaRings;
+        if (USE_WEBKIT_RINGS) {
+            drawNativeRings = !drawJavaRings && !isInTouchMode();
+        }
+        drawContent(canvas, drawNativeRings);
         canvas.restoreToCount(saveCount);
 
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
@@ -4080,16 +4093,22 @@
         }
 
         // paint the highlight in the end
-        if (!mTouchHighlightRegion.isEmpty()) {
-            if (mTouchHightlightPaint == null) {
-                mTouchHightlightPaint = new Paint();
-                mTouchHightlightPaint.setColor(mHightlightColor);
-                mTouchHightlightPaint.setAntiAlias(true);
-                mTouchHightlightPaint.setPathEffect(new CornerPathEffect(
-                        TOUCH_HIGHLIGHT_ARC));
+        if (drawJavaRings) {
+            long delay = System.currentTimeMillis() - mTouchHighlightRequested;
+            if (delay < ViewConfiguration.getTapTimeout()) {
+                Rect r = mTouchHighlightRegion.getBounds();
+                postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
+            } else {
+                if (mTouchHightlightPaint == null) {
+                    mTouchHightlightPaint = new Paint();
+                    mTouchHightlightPaint.setColor(mHightlightColor);
+                }
+                RegionIterator iter = new RegionIterator(mTouchHighlightRegion);
+                Rect r = new Rect();
+                while (iter.next(r)) {
+                    canvas.drawRect(r, mTouchHightlightPaint);
+                }
             }
-            canvas.drawPath(mTouchHighlightRegion.getBoundaryPath(),
-                    mTouchHightlightPaint);
         }
         if (DEBUG_TOUCH_HIGHLIGHT) {
             if (getSettings().getNavDump()) {
@@ -4112,11 +4131,10 @@
         }
     }
 
-    private void removeTouchHighlight(boolean removePendingMessage) {
-        if (removePendingMessage) {
-            mWebViewCore.removeMessages(EventHub.GET_TOUCH_HIGHLIGHT_RECTS);
-        }
-        mWebViewCore.sendMessage(EventHub.REMOVE_TOUCH_HIGHLIGHT_RECTS);
+    private void removeTouchHighlight() {
+        mWebViewCore.removeMessages(EventHub.GET_TOUCH_HIGHLIGHT_RECTS);
+        mPrivateHandler.removeMessages(SET_TOUCH_HIGHLIGHT_RECTS);
+        setTouchHighlightRects(null);
     }
 
     @Override
@@ -5785,8 +5803,8 @@
                     mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
                 } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
                     mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
-                    if (getSettings().supportTouchOnly()) {
-                        removeTouchHighlight(true);
+                    if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
+                        removeTouchHighlight();
                     }
                     if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
                         mTouchMode = TOUCH_DOUBLE_TAP_MODE;
@@ -5809,15 +5827,19 @@
                         mWebViewCore.sendMessage(
                                 EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
                     }
-                    if (getSettings().supportTouchOnly()) {
+                    if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
                         TouchHighlightData data = new TouchHighlightData();
                         data.mX = contentX;
                         data.mY = contentY;
+                        data.mNativeLayerRect = new Rect();
+                        data.mNativeLayer = nativeScrollableLayer(
+                                contentX, contentY, data.mNativeLayerRect, null);
                         data.mSlop = viewToContentDimension(mNavSlop);
+                        mTouchHighlightRegion.setEmpty();
                         if (!mBlockWebkitViewMessages) {
-                            mWebViewCore.sendMessageDelayed(
-                                    EventHub.GET_TOUCH_HIGHLIGHT_RECTS, data,
-                                    ViewConfiguration.getTapTimeout());
+                            mTouchHighlightRequested = System.currentTimeMillis();
+                            mWebViewCore.sendMessageAtFrontOfQueue(
+                                    EventHub.GET_TOUCH_HIGHLIGHT_RECTS, data);
                         }
                         if (DEBUG_TOUCH_HIGHLIGHT) {
                             if (getSettings().getNavDump()) {
@@ -5904,8 +5926,8 @@
                     if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
                         mTouchMode = TOUCH_INIT_MODE;
                     }
-                    if (getSettings().supportTouchOnly()) {
-                        removeTouchHighlight(true);
+                    if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
+                        removeTouchHighlight();
                     }
                 }
                 // pass the touch events from UI thread to WebCore thread
@@ -6382,6 +6404,8 @@
         WebViewCore.reducePriority();
         // to get better performance, pause updating the picture
         WebViewCore.pauseUpdatePicture(mWebViewCore);
+        nativeSetIsScrolling(true);
+
         if (!mDragFromTextInput) {
             nativeHideCursor();
         }
@@ -6478,13 +6502,14 @@
                 || mTouchMode == TOUCH_DRAG_LAYER_MODE) && !mSelectingText) {
             WebViewCore.resumePriority();
             WebViewCore.resumeUpdatePicture(mWebViewCore);
+            nativeSetIsScrolling(false);
         }
         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
         mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
         mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
-        if (getSettings().supportTouchOnly()) {
-            removeTouchHighlight(true);
+        if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
+            removeTouchHighlight();
         }
         mHeldMotionless = MOTIONLESS_TRUE;
         mTouchMode = TOUCH_DONE_MODE;
@@ -7136,8 +7161,20 @@
         int contentX = viewToContentX(mLastTouchX + mScrollX);
         int contentY = viewToContentY(mLastTouchY + mScrollY);
         int slop = viewToContentDimension(mNavSlop);
+        if (USE_WEBKIT_RINGS && !mTouchHighlightRegion.isEmpty()) {
+            // set mTouchHighlightRequested to 0 to cause an immediate
+            // drawing of the touch rings
+            mTouchHighlightRequested = 0;
+            invalidate(mTouchHighlightRegion.getBounds());
+            mPrivateHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    removeTouchHighlight();
+                }
+            }, ViewConfiguration.getPressedStateDuration());
+        }
         if (getSettings().supportTouchOnly()) {
-            removeTouchHighlight(false);
+            removeTouchHighlight();
             WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
             // use "0" as generation id to inform WebKit to use the same x/y as
             // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
@@ -8027,8 +8064,8 @@
                     break;
                 }
                 case SWITCH_TO_LONGPRESS: {
-                    if (getSettings().supportTouchOnly()) {
-                        removeTouchHighlight(false);
+                    if (USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
+                        removeTouchHighlight();
                     }
                     if (inFullScreenMode() || mDeferTouchProcess) {
                         TouchEventData ted = new TouchEventData();
@@ -8350,26 +8387,9 @@
                     break;
 
                 case SET_TOUCH_HIGHLIGHT_RECTS:
-                    invalidate(mTouchHighlightRegion.getBounds());
-                    mTouchHighlightRegion.setEmpty();
-                    if (msg.obj != null) {
-                        ArrayList<Rect> rects = (ArrayList<Rect>) msg.obj;
-                        for (Rect rect : rects) {
-                            Rect viewRect = contentToViewRect(rect);
-                            // some sites, like stories in nytimes.com, set
-                            // mouse event handler in the top div. It is not
-                            // user friendly to highlight the div if it covers
-                            // more than half of the screen.
-                            if (viewRect.width() < getWidth() >> 1
-                                    || viewRect.height() < getHeight() >> 1) {
-                                mTouchHighlightRegion.union(viewRect);
-                                invalidate(viewRect);
-                            } else {
-                                Log.w(LOGTAG, "Skip the huge selection rect:"
-                                        + viewRect);
-                            }
-                        }
-                    }
+                    @SuppressWarnings("unchecked")
+                    ArrayList<Rect> rects = (ArrayList<Rect>) msg.obj;
+                    setTouchHighlightRects(rects);
                     break;
 
                 case SAVE_WEBARCHIVE_FINISHED:
@@ -8406,6 +8426,28 @@
         }
     }
 
+    private void setTouchHighlightRects(ArrayList<Rect> rects) {
+        invalidate(mTouchHighlightRegion.getBounds());
+        mTouchHighlightRegion.setEmpty();
+        if (rects != null) {
+            for (Rect rect : rects) {
+                Rect viewRect = contentToViewRect(rect);
+                // some sites, like stories in nytimes.com, set
+                // mouse event handler in the top div. It is not
+                // user friendly to highlight the div if it covers
+                // more than half of the screen.
+                if (viewRect.width() < getWidth() >> 1
+                        || viewRect.height() < getHeight() >> 1) {
+                    mTouchHighlightRegion.union(viewRect);
+                } else {
+                    Log.w(LOGTAG, "Skip the huge selection rect:"
+                            + viewRect);
+                }
+            }
+            invalidate(mTouchHighlightRegion.getBounds());
+        }
+    }
+
     /** @hide Called by JNI when pages are swapped (only occurs with hardware
      * acceleration) */
     protected void pageSwapCallback() {
@@ -9277,6 +9319,7 @@
      * @return True if the layer is successfully scrolled.
      */
     private native boolean  nativeScrollLayer(int layer, int newX, int newY);
+    private native void     nativeSetIsScrolling(boolean isScrolling);
     private native int      nativeGetBackgroundColor();
     native boolean  nativeSetProperty(String key, String value);
     native String   nativeGetProperty(String key);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 400cdbd..3ca3eaa 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -801,6 +801,8 @@
         int mX;
         int mY;
         int mSlop;
+        int mNativeLayer;
+        Rect mNativeLayerRect;
     }
 
     static class AutoFillData {
@@ -1015,7 +1017,6 @@
         static final int REMOVE_PACKAGE_NAME = 186;
 
         static final int GET_TOUCH_HIGHLIGHT_RECTS = 187;
-        static final int REMOVE_TOUCH_HIGHLIGHT_RECTS = 188;
 
         // accessibility support
         static final int MODIFY_SELECTION = 190;
@@ -1172,6 +1173,7 @@
                                     loadParams.mMimeType,
                                     loadParams.mEncoding,
                                     loadParams.mHistoryUrl);
+                            nativeContentInvalidateAll();
                             break;
 
                         case STOP_LOADING:
@@ -1576,6 +1578,10 @@
 
                         case GET_TOUCH_HIGHLIGHT_RECTS:
                             TouchHighlightData d = (TouchHighlightData) msg.obj;
+                            if (d.mNativeLayer != 0) {
+                                nativeScrollLayer(d.mNativeLayer,
+                                        d.mNativeLayerRect);
+                            }
                             ArrayList<Rect> rects = nativeGetTouchHighlightRects
                                     (d.mX, d.mY, d.mSlop);
                             mWebView.mPrivateHandler.obtainMessage(
@@ -1583,12 +1589,6 @@
                                     .sendToTarget();
                             break;
 
-                        case REMOVE_TOUCH_HIGHLIGHT_RECTS:
-                            mWebView.mPrivateHandler.obtainMessage(
-                                    WebView.SET_TOUCH_HIGHLIGHT_RECTS, null)
-                                    .sendToTarget();
-                            break;
-
                         case USE_MOCK_DEVICE_ORIENTATION:
                             useMockDeviceOrientation();
                             break;
@@ -2070,10 +2070,8 @@
             if (!core.getSettings().enableSmoothTransition()) return;
 
             synchronized (core) {
+                core.nativeSetIsPaused(true);
                 core.mDrawIsPaused = true;
-                if (core.mDrawIsScheduled) {
-                    core.mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
-                }
             }
         }
 
@@ -2082,15 +2080,14 @@
     static void resumeUpdatePicture(WebViewCore core) {
         if (core != null) {
             // if mDrawIsPaused is true, ignore the setting, continue to resume
-            if (!core.mDrawIsPaused
-                    && !core.getSettings().enableSmoothTransition()) return;
+            if (!core.mDrawIsPaused)
+                return;
 
             synchronized (core) {
+                core.nativeSetIsPaused(false);
                 core.mDrawIsPaused = false;
                 // always redraw on resume to reenable gif animations
                 core.mDrawIsScheduled = false;
-                core.nativeContentInvalidateAll();
-                core.contentDraw();
             }
         }
     }
@@ -2127,7 +2124,6 @@
             // only fire an event if this is our first request
             if (mDrawIsScheduled) return;
             mDrawIsScheduled = true;
-            if (mDrawIsPaused) return;
             mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
         }
     }
@@ -2228,9 +2224,9 @@
         }
 
         // remove the touch highlight when moving to a new page
-        if (getSettings().supportTouchOnly()) {
-            mEventHub.sendMessage(Message.obtain(null,
-                    EventHub.REMOVE_TOUCH_HIGHLIGHT_RECTS));
+        if (WebView.USE_WEBKIT_RINGS || getSettings().supportTouchOnly()) {
+            mWebView.mPrivateHandler.sendEmptyMessage(
+                    WebView.SET_TOUCH_HIGHLIGHT_RECTS);
         }
 
         // reset the scroll position, the restored offset and scales
@@ -2789,6 +2785,7 @@
         return mDeviceOrientationService;
     }
 
+    private native void nativeSetIsPaused(boolean isPaused);
     private native void nativePause();
     private native void nativeResume();
     private native void nativeFreeMemory();
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 7ad5d6c..51506e8 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -368,8 +368,10 @@
         } else if (mState == STATE_EXIT) {
             if (alpha == 0) { // Done with exit
                 setState(STATE_NONE);
+            } else if (mTrackDrawable != null) {
+                mList.invalidate(viewWidth - mThumbW, 0, viewWidth, mList.getHeight());
             } else {
-                mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);            
+                mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH);
             }
         }
     }
@@ -597,7 +599,7 @@
 
     private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount,
             int totalItemCount) {
-        if (mSectionIndexer == null) {
+        if (mSectionIndexer == null || mListAdapter == null) {
             getSectionsFromIndexer();
         }
         if (mSectionIndexer == null || !mMatchDragPosition) {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 5e3b956..ff13dcb 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -142,7 +142,7 @@
             final int end = editable.getSpanEnd(spellCheckSpan);
 
             // Do not check this word if the user is currently editing it
-            if (start >= 0 && end >= 0 && (selectionEnd < start || selectionStart > end)) {
+            if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
                 final String word = editable.subSequence(start, end).toString();
                 spellCheckSpan.setSpellCheckInProgress();
                 textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 683a984..c021c48 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4788,8 +4788,7 @@
             selEnd = getSelectionEnd();
 
             if (selStart >= 0) {
-                if (mHighlightPath == null)
-                    mHighlightPath = new Path();
+                if (mHighlightPath == null) mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
                     if (isCursorVisible() &&
@@ -4995,6 +4994,7 @@
             } else {
                 // Selection extends across multiple lines -- the focused
                 // rect covers the entire width.
+                if (mHighlightPath == null) mHighlightPath = new Path();
                 if (mHighlightPathBogus) {
                     mHighlightPath.reset();
                     mLayout.getSelectionPath(selStart, selEnd, mHighlightPath);
@@ -7634,12 +7634,6 @@
                 getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what);
             }
         }
-
-        if (what instanceof SuggestionSpan) {
-            if (newStart < 0) {
-                Log.d("spellcheck", "REMOVE suggspan " + mText.subSequence(oldStart, oldEnd));
-            }
-        }
     }
 
     /**
@@ -10892,6 +10886,11 @@
 
     @Override
     protected void resolveTextDirection() {
+        if (hasPasswordTransformationMethod()) {
+            mTextDir = TextDirectionHeuristics.LOCALE;
+            return;
+        }
+
         // Always need to resolve layout direction first
         final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
 
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index b18af02..4882a12 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -30,7 +30,8 @@
  */
 interface ITextServicesManager {
     SpellCheckerInfo getCurrentSpellChecker(String locale);
-    SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale);
+    SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            String locale, boolean allowImplicitlySelectedSubtype);
     oneway void getSpellCheckerService(String sciId, in String locale,
             in ITextServicesSessionListener tsListener,
             in ISpellCheckerSessionListener scListener, in Bundle bundle);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 4efb29f..8988c9f 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -826,15 +826,18 @@
             rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
         }
 
-        if (mExpandedActionView == null) {
-            boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
-                    (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-            if (showTitle) {
-                availableWidth = measureChildView(mTitleLayout, availableWidth,
-                        MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
-                leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
-            }
+        if (mIndeterminateProgressView != null &&
+                mIndeterminateProgressView.getVisibility() != GONE) {
+            availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
+                    childSpecHeight, 0);
+            rightOfCenter = Math.max(0,
+                    rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
+        }
 
+        final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+                (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+
+        if (mExpandedActionView == null) {
             switch (mNavigationMode) {
                 case ActionBar.NAVIGATION_MODE_LIST:
                     if (mListNavLayout != null) {
@@ -865,14 +868,6 @@
             }
         }
 
-        if (mIndeterminateProgressView != null &&
-                mIndeterminateProgressView.getVisibility() != GONE) {
-            availableWidth = measureChildView(mIndeterminateProgressView, availableWidth,
-                    childSpecHeight, 0);
-            rightOfCenter = Math.max(0,
-                    rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
-        }
-
         View customView = null;
         if (mExpandedActionView != null) {
             customView = mExpandedActionView;
@@ -922,6 +917,13 @@
             customView.measure(
                     MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
                     MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
+            availableWidth -= horizontalMargin + customView.getMeasuredWidth();
+        }
+
+        if (mExpandedActionView == null && showTitle) {
+            availableWidth = measureChildView(mTitleLayout, availableWidth,
+                    MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+            leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
         }
 
         if (mContentHeight <= 0) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index fb5e5fe..bcf8e71 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -222,12 +222,26 @@
     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
 }
 
+static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, SkPaint* paint, jint saveFlags) {
+    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
+            paint, saveFlags);
+}
+
 static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jint alpha, jint saveFlags) {
     return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
 }
 
+static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, jint alpha, jint saveFlags) {
+    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+            alpha, saveFlags);
+}
+
 // ----------------------------------------------------------------------------
 // Clipping
 // ----------------------------------------------------------------------------
@@ -759,7 +773,9 @@
     { "nGetSaveCount",      "(I)I",            (void*) android_view_GLES20Canvas_getSaveCount },
 
     { "nSaveLayer",         "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayer },
+    { "nSaveLayer",         "(III)I",          (void*) android_view_GLES20Canvas_saveLayerClip },
     { "nSaveLayerAlpha",    "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
+    { "nSaveLayerAlpha",    "(III)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
 
     { "nQuickReject",       "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_quickReject },
     { "nClipRect",          "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 1b65492..c5adc38 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index 70c1e262..efcfa26 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index 9fa19ef..490b6f5 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index 8384797..57f2026 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_disabled.png b/core/res/res/drawable-hdpi/combobox_disabled.png
index 50eb45e..85fbc3c 100644
--- a/core/res/res/drawable-hdpi/combobox_disabled.png
+++ b/core/res/res/drawable-hdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/combobox_nohighlight.png b/core/res/res/drawable-hdpi/combobox_nohighlight.png
index 9d60301..2de2abb 100644
--- a/core/res/res/drawable-hdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-hdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
index da28a17..db23635 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
index 015d30a..269a456 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
index df7f236..d997b36 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
index 8950f81..8ed5eb7 100644
--- a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png
index ddb8a71..8e15aba2 100644
--- a/core/res/res/drawable-hdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
index 288b809..3cbafb9 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
index 7866e06..7b019844 100644
--- a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
index 699552d..2b6340ac 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
index 543afa2..49c8c05 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
index e1a5e70..df1db0e 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
index b778741..fbc46d0 100644
--- a/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
index 8a5d810..87e31e1 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
index c423a74..080fc78 100644
--- a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_adb.png b/core/res/res/drawable-ldpi/stat_sys_adb.png
index 86b945b..aec8d90 100644
--- a/core/res/res/drawable-ldpi/stat_sys_adb.png
+++ b/core/res/res/drawable-ldpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 86debc4..abf6493 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index b403e67..71b052b 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index d06361a..87c62ff 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index a4dae66..51821fa 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_disabled.png b/core/res/res/drawable-mdpi/combobox_disabled.png
index 94ad006..ac8a235 100644
--- a/core/res/res/drawable-mdpi/combobox_disabled.png
+++ b/core/res/res/drawable-mdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/combobox_nohighlight.png b/core/res/res/drawable-mdpi/combobox_nohighlight.png
index 75d642c..9d60e26 100644
--- a/core/res/res/drawable-mdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-mdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
index 0fc20e0..84d4c11 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
index 2b7a262..d922ef1 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
index 1410805..8c37c8d 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
index 34d79f6..e442c28 100644
--- a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb.png b/core/res/res/drawable-mdpi/stat_sys_adb.png
index 730d96f..ebedfa3 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
index 99840b1..039af2f 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
index 6bd9509..eb70db6 100644
--- a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
index 22493de..9b45bb7 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
index 02b491c..67b96e2 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
index 16c4c1a..b09f9dc 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
index e474bc5..821ad91 100644
--- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
index c56ab9c..c3a7a2e 100644
--- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
index a2e5944..e769cb5 100644
--- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png
index e619ed5..faabda1 100644
--- a/core/res/res/drawable-nodpi/platlogo.png
+++ b/core/res/res/drawable-nodpi/platlogo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
index a364792..aca0a23 100644
--- a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
index 5a52ad6..7dc088a 100644
--- a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
index e34ed85..a97c1d3 100644
--- a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
index f76d56b..25d139a 100644
--- a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_disabled.png b/core/res/res/drawable-xhdpi/combobox_disabled.png
index 9edf16e..e8ca0b0 100644
--- a/core/res/res/drawable-xhdpi/combobox_disabled.png
+++ b/core/res/res/drawable-xhdpi/combobox_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/combobox_nohighlight.png b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
index 0b58042..d75bb06 100644
--- a/core/res/res/drawable-xhdpi/combobox_nohighlight.png
+++ b/core/res/res/drawable-xhdpi/combobox_nohighlight.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
index 3c8979f..9cf9173 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
index 45b7adb..c8d8a17 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
index e258284a..e3793f7 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
index 5c4bbf5..c0be34f0 100644
--- a/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
+++ b/core/res/res/drawable-xhdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_adb.png b/core/res/res/drawable-xhdpi/stat_sys_adb.png
index 01eb61d..92f8dd4 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
index 1a1a9c4..59a9a1b 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
index 462cea6..5d472c8 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
index 3e178b2..3dbef60 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
index 4c34b93..197c2bc 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
index cf1b3ca..a765e5b 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
index 0ee383b..30a3237 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_right_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png
index 42c019e..3c8ed1e 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
index 63efe71..f69ebc5 100644
--- a/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
+++ b/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
deleted file mode 100644
index 08f6453..0000000
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/layout/list_content.xml
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
-
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="0px"
-        android:layout_marginTop="@dimen/preference_screen_top_margin"
-        android:layout_marginBottom="@dimen/preference_screen_bottom_margin"
-        android:layout_weight="1">
-
-        <LinearLayout
-            android:id="@+id/headers"
-            android:orientation="vertical"
-            android:layout_width="0px"
-            android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/preference_screen_side_margin_negative"
-            android:layout_marginLeft="@dimen/preference_screen_side_margin"
-            android:layout_weight="@integer/preferences_left_pane_weight">
-
-            <ListView android:id="@android:id/list"
-                android:layout_width="match_parent"
-                android:layout_height="0px"
-                android:layout_weight="1"
-                android:paddingLeft="@dimen/preference_screen_header_padding_side"
-                android:paddingRight="@dimen/preference_screen_header_padding_side"
-                android:paddingTop="@dimen/preference_screen_header_vertical_padding"
-                android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
-                android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
-                android:drawSelectorOnTop="false"
-                android:cacheColorHint="@android:color/transparent"
-                android:listPreferredItemHeight="48dp"
-                android:scrollbarAlwaysDrawVerticalTrack="true" />
-
-            <FrameLayout android:id="@+id/list_footer"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0" />
-
-        </LinearLayout>
-
-        <LinearLayout
-                android:id="@+id/prefs_frame"
-                android:layout_width="0px"
-                android:layout_height="match_parent"
-                android:layout_weight="@integer/preferences_right_pane_weight"
-                android:layout_marginLeft="@dimen/preference_screen_side_margin"
-                android:layout_marginRight="@dimen/preference_screen_side_margin"
-                android:background="?attr/detailsElementBackground"
-                android:orientation="vertical"
-                android:visibility="gone" >
-
-            <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
-                empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
-                the action bar. -->
-            <include layout="@layout/breadcrumbs_in_fragment" />
-
-            <android.preference.PreferenceFrameLayout android:id="@+id/prefs"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dip"
-                    android:layout_weight="1"
-                />
-        </LinearLayout>
-    </LinearLayout>
-
-    <RelativeLayout android:id="@+id/button_bar"
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:layout_weight="0"
-        android:visibility="gone">
-
-        <Button android:id="@+id/back_button"
-            android:layout_width="150dip"
-            android:layout_height="wrap_content"
-            android:layout_margin="5dip"
-            android:layout_alignParentLeft="true"
-            android:text="@string/back_button_label"
-        />
-        <LinearLayout
-            android:orientation="horizontal"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true">
-
-            <Button android:id="@+id/skip_button"
-                android:layout_width="150dip"
-                android:layout_height="wrap_content"
-                android:layout_margin="5dip"
-                android:text="@string/skip_button_label"
-                android:visibility="gone"
-            />
-
-            <Button android:id="@+id/next_button"
-                android:layout_width="150dip"
-                android:layout_height="wrap_content"
-                android:layout_margin="5dip"
-                android:text="@string/next_button_label"
-            />
-        </LinearLayout>
-    </RelativeLayout>
-</LinearLayout>
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index 8b18454..3313590 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -24,7 +24,7 @@
     android:layout_height="match_parent"
     android:divider="?android:attr/dividerHorizontal"
     android:showDividers="middle"
-    android:dividerPadding="16dip" >
+    android:dividerPadding="0dip" >
 
     <!-- The list of packages that correspond to the requesting UID
     and the account/authtokenType that is being requested -->
@@ -123,20 +123,20 @@
     <LinearLayout
         android:id="@+id/buttons"
         android:layout_width="match_parent"
-        android:layout_height="54dip"
+        android:layout_height="wrap_content"
         style="?android:attr/buttonBarStyle">
 
         <Button
-            android:id="@+id/allow_button"
-            android:text="@string/allow"
+            android:id="@+id/deny_button"
+            android:text="@string/deny"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="2"
             style="?android:attr/buttonBarButtonStyle" />
 
         <Button
-            android:id="@+id/deny_button"
-            android:text="@string/deny"
+            android:id="@+id/allow_button"
+            android:text="@string/allow"
             android:layout_width="0dip"
             android:layout_height="wrap_content"
             android:layout_weight="2"
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 62181b5..70bc59a 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -27,8 +27,6 @@
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="0px"
-        android:layout_marginTop="@dimen/preference_screen_top_margin"
-        android:layout_marginBottom="@dimen/preference_screen_bottom_margin"
         android:layout_weight="1">
 
         <LinearLayout
@@ -48,6 +46,7 @@
                 android:paddingRight="@dimen/preference_screen_header_padding_side"
                 android:paddingTop="@dimen/preference_screen_header_vertical_padding"
                 android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
+                android:clipToPadding="false"
                 android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
@@ -63,11 +62,10 @@
 
         <LinearLayout
                 android:id="@+id/prefs_frame"
+                style="?attr/preferencePanelStyle"
                 android:layout_width="0px"
                 android:layout_height="match_parent"
                 android:layout_weight="@integer/preferences_right_pane_weight"
-                android:layout_marginLeft="@dimen/preference_screen_side_margin"
-                android:layout_marginRight="@dimen/preference_screen_side_margin"
                 android:orientation="vertical"
                 android:visibility="gone" >
 
diff --git a/core/res/res/layout/preference_list_content_single.xml b/core/res/res/layout/preference_list_content_single.xml
index 6902ffd..259869d 100644
--- a/core/res/res/layout/preference_list_content_single.xml
+++ b/core/res/res/layout/preference_list_content_single.xml
@@ -39,6 +39,9 @@
                 android:layout_height="0px"
                 android:layout_weight="1"
                 android:drawSelectorOnTop="false"
+                android:paddingLeft="@dimen/preference_fragment_padding_side"
+                android:paddingRight="@dimen/preference_fragment_padding_side"
+                android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
                 android:scrollbarAlwaysDrawVerticalTrack="true" />
diff --git a/core/res/res/values-h720dp/dimens.xml b/core/res/res/values-h720dp/dimens.xml
index 7efe322..6e99183 100644
--- a/core/res/res/values-h720dp/dimens.xml
+++ b/core/res/res/values-h720dp/dimens.xml
@@ -21,10 +21,6 @@
     <dimen name="alert_dialog_button_bar_height">54dip</dimen>
     <!-- Preference fragment padding, bottom -->
     <dimen name="preference_fragment_padding_bottom">16dp</dimen>
-    <!-- Preference activity top margin -->
-    <dimen name="preference_screen_top_margin">16dp</dimen>
-    <!-- Preference activity bottom margin -->
-    <dimen name="preference_screen_bottom_margin">16dp</dimen>
 
     <dimen name="preference_screen_header_padding_side">0dip</dimen>
 
diff --git a/core/res/res/values-large/styles.xml b/core/res/res/values-large/styles.xml
deleted file mode 100644
index 5206d7c..0000000
--- a/core/res/res/values-large/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<resources>
-    <style name="PreferencePanel">
-        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginTop">48dip</item>
-        <item name="android:layout_marginBottom">48dip</item>
-        <item name="android:background">?attr/detailsElementBackground</item>
-    </style>
-</resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 24d5d8d..792066e 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,13 +45,7 @@
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
 
     <!-- Preference activity, vertical padding for the header list -->
-    <dimen name="preference_screen_header_vertical_padding">16dp</dimen>
-
-    <!-- Reduce the margin when using dual pane -->
-    <!-- Preference activity side margins -->
-    <dimen name="preference_screen_side_margin">0dp</dimen>
-    <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
+    <dimen name="preference_screen_header_vertical_padding">32dp</dimen>
 
 </resources>
 
diff --git a/core/res/res/values-sw600dp/styles.xml b/core/res/res/values-sw600dp/styles.xml
index 7dea9b8..f9e95b7 100644
--- a/core/res/res/values-sw600dp/styles.xml
+++ b/core/res/res/values-sw600dp/styles.xml
@@ -25,4 +25,12 @@
         <item name="android:measureWithLargestChild">true</item>
         <item name="android:tabLayout">@android:layout/tab_indicator_holo</item>
     </style>
+
+    <style name="PreferencePanel">
+        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
+        <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
+        <item name="android:background">?attr/detailsElementBackground</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a536961..93cbde5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5110,6 +5110,10 @@
              Defaults to false.
              -->
         <attr name="isAlwaysSyncable" format="boolean"/>
+        <!-- If provided, specifies the action of the settings
+             activity for this SyncAdapter.
+             -->
+        <attr name="settingsActivity"/>
     </declare-styleable>
 
     <!-- =============================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8fbb09e..b155b803 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -582,21 +582,6 @@
          If false, Content-disposition fragments are ignored -->
     <bool name="config_mms_content_disposition_support">true</bool>
 
-    <!-- If this value is true, the carrier supports sms delivery reports.
-         If false, sms delivery reports are not supported and the preference
-         option to enable/disable delivery reports is removed in the Messaging app. -->
-    <bool name="config_sms_delivery_reports_support">true</bool>
-
-    <!-- If this value is true, the carrier supports mms delivery reports.
-         If false, mms delivery reports are not supported and the preference
-         option to enable/disable delivery reports is removed in the Messaging app. -->
-    <bool name="config_mms_delivery_reports_support">true</bool>
-
-    <!-- If this value is true, the carrier supports mms read reports.
-         If false, mms read reports are not supported and the preference
-         option to enable/disable read reports is removed in the Messaging app. -->
-    <bool name="config_mms_read_reports_support">true</bool>
-
     <!-- National Language Identifier codes for the following two config items.
          (from 3GPP TS 23.038 V9.1.1 Table 6.2.1.2.4.1):
           0  - reserved
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c522c1e..62a2187 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -78,7 +78,7 @@
     <!-- Preference activity side margins -->
     <dimen name="preference_screen_side_margin">0dp</dimen>
     <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">0dp</dimen>
+    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
     <!-- Preference activity top margin -->
     <dimen name="preference_screen_top_margin">0dp</dimen>
     <!-- Preference activity bottom margin -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9455124..a3e460e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2665,8 +2665,8 @@
 
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
      <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
-     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is a partial string of the message, which will also include the (possibly truncated) hotspot name. -->
-    <string name="wifi_watchdog_network_disabled_detailed"> has a poor internet connection.</string>
+     <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  The complete alert msg is: <hotspot name> + this string, i.e. "Linksys has a poor internet connection" -->
+    <string name="wifi_watchdog_network_disabled_detailed">\u0020has a poor internet connection.</string>
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
diff --git a/core/tests/coretests/src/android/util/LocaleUtilTest.java b/core/tests/coretests/src/android/util/LocaleUtilTest.java
index 203781f..ff3d539 100644
--- a/core/tests/coretests/src/android/util/LocaleUtilTest.java
+++ b/core/tests/coretests/src/android/util/LocaleUtilTest.java
@@ -23,7 +23,6 @@
 import dalvik.annotation.TestTargetNew;
 
 import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
-import static android.util.LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
 
 public class LocaleUtilTest extends AndroidTestCase {
 
@@ -33,7 +32,7 @@
         args = {Locale.class}
     )
     public void testGetLayoutDirectionFromLocale() {
-        assertEquals(TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
                 LocaleUtil.getLayoutDirectionFromLocale(null));
 
         assertEquals(TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
@@ -59,7 +58,7 @@
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
 
-        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
+        assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
 
         assertEquals(LocaleUtil.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
index 7b550eed..6e0932e 100644
--- a/data/fonts/AndroidClock.ttf
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
index a95d548..6e0932e 100644
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf
index 108839e..6e0932e 100644
--- a/data/fonts/AndroidClock_Solid.ttf
+++ b/data/fonts/AndroidClock_Solid.ttf
Binary files differ
diff --git a/docs/html/guide/appendix/install-location.jd b/docs/html/guide/appendix/install-location.jd
index 617f4fc..292d3e7 100644
--- a/docs/html/guide/appendix/install-location.jd
+++ b/docs/html/guide/appendix/install-location.jd
@@ -195,7 +195,7 @@
 <p>In simple terms, anything that does not use the features listed in the previous section
 are safe when installed on external storage. Large games are more commonly the types of
 applications that should allow installation on external storage, because games don't typically
-provide additional services when innactive. When external storage becomes unavailable and a game
+provide additional services when inactive. When external storage becomes unavailable and a game
 process is killed, there should be no visible effect when the storage becomes available again and
 the user restarts the game (assuming that the game properly saved its state during the normal
 <a href="{@docRoot}guide/topics/fundamentals/activities.html#Lifecycle">Activity lifecycle</a>).</p>
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index bde170e..e08119f 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -41,7 +41,8 @@
 
 <p class="note"><strong>Note:</strong> When developing on a device, keep in mind that you should
 still use the <a
-href="{@docRoot}guide/developing/devices/emulator.html">Android emulator</a> to test your application
+href="{@docRoot}guide/developing/devices/emulator.html">Android emulator</a> to test your
+application
 on configurations that are not equivalent to those of your real device. Although the emulator
 does not allow you to test every device feature (such as the accelerometer), it does
 allow you to verify that your application functions properly on different versions of the Android
@@ -56,14 +57,22 @@
 <ol>
   <li>Declare your application as "debuggable" in your Android Manifest.
     <p>In Eclipse, you can do this from the <b>Application</b> tab when viewing the Manifest
-    (on the right side, set <b>Debuggable</b> to <em>true</em>). Otherwise, in the <code>AndroidManifest.xml</code>
-    file, add <code>android:debuggable="true"</code> to the <code>&lt;application></code> element.</p>
+    (on the right side, set <b>Debuggable</b> to <em>true</em>). Otherwise, in the
+<code>AndroidManifest.xml</code>
+    file, add <code>android:debuggable="true"</code> to the <code>&lt;application></code>
+element.</p>
+  </li>
+  <li>Set up your device to allow installation of non-Market applications. <p>On
+the device, go to <strong>Settings > Applications</strong> and enable
+
+<strong>Unknown sources</strong>.</p>
+  
   </li>
   <li>Turn on "USB Debugging" on your device.
-    <p>On the device, go to the home screen, press <b>MENU</b>, select <b>Applications</b> > <b>Development</b>,
-    then enable <b>USB debugging</b>.</p>
+    <p>On the device, go to <strong>Settings > Applications > Development</strong>
+    and enable <strong>USB debugging</strong>.</p>
   </li>
-  <li>Setup your system to detect your device.
+  <li>Set up your system to detect your device.
     <ul>
       <li>If you're developing on Windows, you need to install a USB driver
       for adb. If you're using an Android Developer Phone (ADP), Nexus One, or Nexus S,
@@ -71,27 +80,37 @@
       Driver</a>. Otherwise, you can find a link to the appropriate OEM driver in the
   <a href="{@docRoot}sdk/oem-usb.html">OEM USB Drivers</a> document.</li>
       <li>If you're developing on Mac OS X, it just works. Skip this step.</li>
-      <li>If you're developing on Ubuntu Linux, you need to add a rules file
-that contains a USB configuration for each type of device you want to use for
-development. Each device manufacturer uses a different vendor ID. The
-example rules files below show how to add an entry for a single vendor ID
-(the HTC vendor ID). In order to support more devices, you will need additional
-lines of the same format that provide a different value for the
-<code>SYSFS{idVendor}</code> property. For other IDs, see the table of <a
-href="#VendorIds">USB Vendor IDs</a>, below.
-        <ol>
-          <li>Log in as root and create this file:
-            <code>/etc/udev/rules.d/51-android.rules</code>.
-            <p>For Gusty/Hardy, edit the file to read:<br/>
-            <code>SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4",
-            MODE="0666"</code></p>
+      
+      <li>If you're developing on Ubuntu Linux, you need to add a <a
+href="http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html">
+<code>udev</code></a> 
+rules file that contains a USB configuration for each type of device
+you want to use for development. In the rules file, each device manufacturer
+is identified by a unique vendor ID, as specified by the
+<code>ATTR{idVendor}</code> property. For a list of vendor IDs, see  <a
+href="#VendorIds">USB Vendor IDs</a>, below. To set up device detection on
+Ubuntu Linux:
 
-            <p>For Dapper, edit the file to read:<br/>
-            <code>SUBSYSTEM=="usb_device", SYSFS{idVendor}=="0bb4",
-            MODE="0666"</code></p>
+        <ol type="a">
+          <li>Log in as root and create this file:
+            <code>/etc/udev/rules.d/51-android.rules</code></span>.
+            <p>Use this format to add each vendor to the file:<br/>
+              <code>SUBSYSTEM==&quot;usb&quot;, ATTR{idVendor}==&quot;0bb4&quot;, MODE=&quot;0666&quot;, GROUP=&quot;plugdev&quot;</code>
+              <br /><br />
+              
+              In this example, the vendor ID is for HTC. The <code>MODE</code>
+assignment specifies read/write permissions, and <code>GROUP</code> defines
+which Unix group  owns the device node. </p>
+            
+            <p class="note"><strong>Note:</strong> The rule syntax
+may vary slightly depending on your  environment. Consult the <code>udev</code>
+documentation for your system as needed. For an overview of rule syntax, see
+this guide to <a
+href="http://www.reactivated.net/writing_udev_rules.html">writing udev
+rules</a>.</p>
           </li>
           <li>Now execute:<br/>
-              <code>chmod a+r /etc/udev/rules.d/51-android.rules</code>
+            <code>chmod a+r /etc/udev/rules.d/51-android.rules</code>
           </li>
         </ol>
       </li>
@@ -99,79 +118,143 @@
   </li>
 </ol>
 
-<p>You can verify that your device is connected by executing <code>adb devices</code> from your 
-SDK {@code platform-tools/} directory. If connected, you'll see the device name listed as a
-"device."</p>
+<p>You can verify that your device is connected by executing <code>adb
+devices</code> from your SDK {@code platform-tools/} directory. If connected,
+you'll see the device name listed as a "device."</p>
 
-<p>If using Eclipse, run or debug as usual. You will be presented
-with a <b>Device Chooser</b> dialog that lists the available emulator(s) and connected device(s).
-Select the device upon which you want to install and run the application.</p>
+<p>If using Eclipse, run or debug your application as usual. You will be
+presented with a <b>Device Chooser</b> dialog that lists the available
+emulator(s) and connected device(s). Select the device upon which you want to
+install and run the application.</p>
 
-<p>If using the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb),
-you can issue commands with the <code>-d</code> flag to target your
-connected device.</p>
-
+<p>If using the <a href="{@docRoot}guide/developing/tools/adb.html">Android
+Debug Bridge</a> (adb), you can issue commands with the <code>-d</code> flag to
+target your connected device.</p>
 
 <h3 id="VendorIds">USB Vendor IDs</h3>
-<p>This table provides a reference to the vendor IDs needed in order to add
-USB device support on Linux. The USB Vendor ID is the value given to the
-<code>SYSFS{idVendor}</code> property in the rules file, as described in step 3, above.</p>
+
+<p>This table provides a reference to the vendor IDs needed in order to add USB
+device support on Linux. The USB Vendor ID is the value given to the
+<code>ATTR{idVendor}</code> property in the rules file, as described 
+above.</p>
 
 <table>
   <tr>
     <th>Company</th><th>USB Vendor ID</th></tr>
   <tr>
     <td>Acer</td>
-    <td><code>0502</code></td></tr>
+    <td><code>0502</code></td>
+  </tr>
+  <tr>
+    <td>ASUS</td>
+    <td><code>0B05</code></td>
+  </tr>
   <tr>
     <td>Dell</td>
-    <td><code>413c</code></td></tr>
+    <td><code>413C</code></td>
+  </tr>
   <tr>
     <td>Foxconn</td>
-    <td><code>0489</code></td></tr>
+    <td><code>0489</code></td>
+  </tr>
   <tr>
     <td>Garmin-Asus</td>
-    <td><code>091E</code></td></tr>
+    <td><code>091E</code></td>
+  </tr>
   <tr>
     <td>Google</td>
-    <td><code>18d1</code></td></tr>
+    <td><code>18D1</code></td>
+  </tr>
   <tr>
     <td>HTC</td>
-    <td><code>0bb4</code></td></tr>
+    <td><code>0BB4</code></td>
+  </tr>
   <tr>
     <td>Huawei</td>
-    <td><code>12d1</code></td></tr>
+    <td><code>12D1</code></td>
+  </tr>
   <tr>
     <td>K-Touch</td>
-    <td><code>24e3</code></td></tr>
+    <td><code>24E3</code></td>
+  </tr>
+  <tr>
+    <td>KT Tech</td>
+    <td><code>2116</code></td>
+  </tr>
   <tr>
     <td>Kyocera</td>
-    <td><code>0482</code></td></tr>
+    <td><code>0482</code></td>
+  </tr>
   <tr>
     <td>Lenevo</td>
-    <td><code>17EF</code></td></tr>
+    <td><code>17EF</code></td>
+  </tr>
   <tr>
     <td>LG</td>
-    <td><code>1004</code></td></tr>
+    <td><code>1004</code></td>
+  </tr>
   <tr>
     <td>Motorola</td>
-    <td><code>22b8</code></td></tr>
+    <td><code>22B8</code></td>
+  </tr>
+  <tr>
+    <td>NEC</td>
+    <td><code>0409</code></td>
+  </tr>
+  <tr>
+    <td>Nook</td>
+    <td><code>2080</code></td>
+  </tr>
   <tr>
     <td>Nvidia</td>
-    <td><code>0955</code></td></tr>
+    <td><code>0955</code></td>
+  </tr>
+  <tr>
+    <td>OTGV</td>
+    <td><code>2257</code></td>
+  </tr>
   <tr>
     <td>Pantech</td>
-    <td><code>10A9</code></td></tr>
+    <td><code>10A9</code></td>
+  </tr>
+  <tr>
+    <td>Pegatron</td>
+    <td><code>1D4D</code></td>
+  </tr>
+  <tr>
+    <td>Philips</td>
+    <td><code>0471</code></td>
+  </tr>
+  <tr>
+    <td>PMC-Sierra</td>
+    <td><code>04DA</code></td>
+  </tr>
+  <tr>
+    <td>Qualcomm</td>
+    <td><code>05C6</code></td>
+  </tr>
+  <tr>
+    <td>SK Telesys</td>
+    <td><code>1F53</code></td>
+  </tr>
   <tr>
     <td>Samsung</td>
-    <td><code>04e8</code></td></tr>
+    <td><code>04E8</code></td>
+  </tr>
   <tr>
     <td>Sharp</td>
-    <td><code>04dd</code></td></tr>
+    <td><code>04DD</code></td>
+  </tr>
   <tr>
     <td>Sony Ericsson</td>
-    <td><code>0fce</code></td></tr>
+    <td><code>0FCE</code></td>
+  </tr>
+  <tr>
+    <td>Toshiba</td>
+    <td><code>0930</code></td>
+  </tr>
   <tr>
     <td>ZTE</td>
-    <td><code>19D2</code></td></tr>
+    <td><code>19D2</code></td>
+  </tr>
 </table>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 18f47a6..bbf7cbe 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -22,6 +22,11 @@
     </li>
     <li><a href="#updating">Updating the ADT Plugin</a></li>
   </ol>
+  
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a></li>
+  </ol>
 
 </div>
 </div>
@@ -50,6 +55,12 @@
 how to update ADT to the latest version or how to uninstall it, if necessary.
 </p>
 
+<p>For information about the features provided by the ADT plugin, such as code
+editor features, SDK tool integration, and the graphical layout editor (for drag-and-drop layout
+editing), see the <a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a>
+document.</p>
+
+
 <h2 id="notes">Revisions</h2>
 
 <p>The sections below provide notes about successive releases of
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index 3c2ba8b..ad3be4a 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -92,6 +92,8 @@
 href="http://developer.motorola.com/docstools/USB_Drivers/">http://developer.motorola.com/docstools/USB_Drivers/</a></td>
 </tr><tr><td>Pantech</td>	<td><a
 href="http://www.isky.co.kr/cs/software/software.sky?fromUrl=index">http://www.isky.co.kr/cs/software/software.sky?fromUrl=index</a></td>
+</tr><tr><td>Pegatron</td>	<td><a
+href="http://www.pegatroncorp.com/download/New_Duke_PC_Driver_0705.zip">http://www.pegatroncorp.com/download/New_Duke_PC_Driver_0705.zip</a> (ZIP download)</td>
 </tr><tr><td>Samsung</td>	<td><a
 href="http://www.samsung.com/us/support/downloads">http://www.samsung.com/us/support/downloads</a></td>
 </tr><tr><td>Sharp</td>	<td><a
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index df30e8c..923518d 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -481,6 +481,7 @@
     bool                    mMarkerReached;
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
+    bool                    mFlushed; // FIXME will be made obsolete by making flush() synchronous
     uint32_t                mFlags;
     int                     mSessionId;
     int                     mAuxEffectId;
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
index c1bd4ed..2e5fd73 100644
--- a/include/media/stagefright/foundation/ALooperRoster.h
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -31,9 +31,14 @@
 
     void unregisterHandler(ALooper::handler_id handlerID);
 
-    void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
+    status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
     void deliverMessage(const sp<AMessage> &msg);
 
+    status_t postAndAwaitResponse(
+            const sp<AMessage> &msg, sp<AMessage> *response);
+
+    void postReply(uint32_t replyID, const sp<AMessage> &reply);
+
     sp<ALooper> findLooper(ALooper::handler_id handlerID);
 
 private:
@@ -45,6 +50,12 @@
     Mutex mLock;
     KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
     ALooper::handler_id mNextHandlerID;
+    uint32_t mNextReplyID;
+    Condition mRepliesCondition;
+
+    KeyedVector<uint32_t, sp<AMessage> > mReplies;
+
+    status_t postMessage_l(const sp<AMessage> &msg, int64_t delayUs);
 
     DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
 };
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 72dc730..7ec54aa 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -72,6 +72,17 @@
 
     void post(int64_t delayUs = 0);
 
+    // Posts the message to its target and waits for a response (or error)
+    // before returning.
+    status_t postAndAwaitResponse(sp<AMessage> *response);
+
+    // If this returns true, the sender of this message is synchronously
+    // awaiting a response, the "replyID" can be used to send the response
+    // via "postReply" below.
+    bool senderAwaitsResponse(uint32_t *replyID) const;
+
+    void postReply(uint32_t replyID);
+
     // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
     // their refcount incremented.
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ac9b33b..79a01a3 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -608,6 +608,9 @@
             if (mConnectedApi == api) {
                 drainQueueAndFreeBuffersLocked();
                 mConnectedApi = NO_CONNECTED_API;
+                mNextCrop.makeInvalid();
+                mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+                mNextTransform = 0;
                 mDequeueCondition.signal();
             } else {
                 LOGE("disconnect: connected to another api (cur=%d, req=%d)",
@@ -1022,7 +1025,7 @@
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
             mCurrentTransform, mCurrentTexture,
             prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
-            mCurrentTransform, fifoSize, fifo.string()
+            mNextTransform, fifoSize, fifo.string()
     );
     result.append(buffer);
 
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 5a35b4d..710ef94 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -407,8 +407,15 @@
     LOGV("SurfaceTextureClient::disconnect");
     Mutex::Autolock lock(mMutex);
     int err = mSurfaceTexture->disconnect(api);
-    if (!err && api == NATIVE_WINDOW_API_CPU) {
-        mConnectedToCpu = false;
+    if (!err) {
+        freeAllBuffers();
+        mReqFormat = 0;
+        mReqWidth = 0;
+        mReqHeight = 0;
+        mReqUsage = 0;
+        if (api == NATIVE_WINDOW_API_CPU) {
+            mConnectedToCpu = false;
+        }
     }
     return err;
 }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 88cfc5a..cedf456 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -194,6 +194,7 @@
 
 void DisplayList::init() {
     mSize = 0;
+    mIsRenderable = true;
 }
 
 size_t DisplayList::getSize() {
@@ -892,7 +893,7 @@
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
+DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE), mHasDrawOps(false) {
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -926,6 +927,8 @@
     mPathMap.clear();
 
     mMatrices.clear();
+
+    mHasDrawOps = false;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -938,6 +941,7 @@
     } else {
         displayList->initFromDisplayListRenderer(*this, true);
     }
+    displayList->setRenderable(mHasDrawOps);
     return displayList;
 }
 
@@ -982,7 +986,11 @@
 }
 
 void DisplayListRenderer::restore() {
-    addOp(DisplayList::Restore);
+    if (mRestoreSaveCount < 0) {
+        addOp(DisplayList::Restore);
+    } else {
+        mRestoreSaveCount--;
+    }
     OpenGLRenderer::restore();
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 69e72a4..8cd7fea 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -63,6 +63,7 @@
     // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
     //            when modifying this file
     enum Op {
+        // Non-drawing operations
         Save = 0,
         Restore,
         RestoreToCount,
@@ -75,6 +76,7 @@
         SetMatrix,
         ConcatMatrix,
         ClipRect,
+        // Drawing operations
         DrawDisplayList,
         DrawLayer,
         DrawBitmap,
@@ -113,6 +115,14 @@
 
     static void outputLogBuffer(int fd);
 
+    void setRenderable(bool renderable) {
+        mIsRenderable = renderable;
+    }
+
+    bool isRenderable() const {
+        return mIsRenderable;
+    }
+
 private:
     void init();
 
@@ -207,6 +217,8 @@
     mutable SkFlattenableReadBuffer mReader;
 
     size_t mSize;
+
+    bool mIsRenderable;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -328,6 +340,7 @@
     inline void addOp(DisplayList::Op drawOp) {
         insertRestoreToCount();
         mWriter.writeInt(drawOp);
+        mHasDrawOps = mHasDrawOps || drawOp >= DisplayList::DrawDisplayList;
     }
 
     inline void addInt(int value) {
@@ -479,6 +492,7 @@
     SkWriter32 mWriter;
 
     int mRestoreSaveCount;
+    bool mHasDrawOps;
 
     friend class DisplayList;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 04f3c58..a20a88e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1278,7 +1278,7 @@
 
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
-    if (displayList) {
+    if (displayList && displayList->isRenderable()) {
         return displayList->replay(*this, dirty, level);
     }
 
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index e6331ce..2bdd3c9 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -722,20 +722,22 @@
      */
 
     private Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) {
-        final int width = bitmap.getWidth();
-        final int height = bitmap.getHeight();
-        if (width > maxWidth || height > maxHeight) {
-            float scale = Math.min((float) maxWidth / width, (float) maxHeight / height);
-            int newWidth = Math.round(scale * width);
-            int newHeight = Math.round(scale * height);
-            Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.getConfig());
-            Canvas canvas = new Canvas(outBitmap);
-            Paint paint = new Paint();
-            paint.setAntiAlias(true);
-            paint.setFilterBitmap(true);
-            canvas.drawBitmap(bitmap, null,
-                    new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint);
-            bitmap = outBitmap;
+        if (bitmap != null) {
+            final int width = bitmap.getWidth();
+            final int height = bitmap.getHeight();
+            if (width > maxWidth || height > maxHeight) {
+                float scale = Math.min((float) maxWidth / width, (float) maxHeight / height);
+                int newWidth = Math.round(scale * width);
+                int newHeight = Math.round(scale * height);
+                Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.getConfig());
+                Canvas canvas = new Canvas(outBitmap);
+                Paint paint = new Paint();
+                paint.setAntiAlias(true);
+                paint.setFilterBitmap(true);
+                canvas.drawBitmap(bitmap, null,
+                        new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint);
+                bitmap = outBitmap;
+            }
         }
         return bitmap;
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 3949c39..cecedb5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -259,6 +259,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mFlushed = false;
     mFlags = flags;
     AudioSystem::acquireAudioSessionId(mSessionId);
 
@@ -337,6 +338,7 @@
     audio_track_cblk_t* cblk = mCblk;
 
     if (mActive == 0) {
+        mFlushed = false;
         mActive = 1;
         mNewPosition = cblk->server + mUpdatePeriod;
         cblk->lock.lock();
@@ -437,6 +439,7 @@
     mUpdatePeriod = 0;
 
     if (!mActive) {
+        mFlushed = true;
         mAudioTrack->flush();
         // Release AudioTrack callback thread in case it was waiting for new buffers
         // in AudioTrack::obtainBuffer()
@@ -655,7 +658,7 @@
 {
     if (position == 0) return BAD_VALUE;
     AutoMutex lock(mLock);
-    *position = mCblk->server;
+    *position = mFlushed ? 0 : mCblk->server;
 
     return NO_ERROR;
 }
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index dd69e6b..d41ab1b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -180,6 +180,8 @@
         } else {
             mAudioTrack->stop();
         }
+
+        mNumFramesPlayed = 0;
     } else {
         if (mAudioSink.get() != NULL) {
             mAudioSink->pause();
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 8aa1b15..e399f2f 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -27,7 +27,8 @@
 namespace android {
 
 ALooperRoster::ALooperRoster()
-    : mNextHandlerID(1) {
+    : mNextHandlerID(1),
+      mNextReplyID(1) {
 }
 
 ALooper::handler_id ALooperRoster::registerHandler(
@@ -70,15 +71,19 @@
     mHandlers.removeItemsAt(index);
 }
 
-void ALooperRoster::postMessage(
+status_t ALooperRoster::postMessage(
         const sp<AMessage> &msg, int64_t delayUs) {
     Mutex::Autolock autoLock(mLock);
+    return postMessage_l(msg, delayUs);
+}
 
+status_t ALooperRoster::postMessage_l(
+        const sp<AMessage> &msg, int64_t delayUs) {
     ssize_t index = mHandlers.indexOfKey(msg->target());
 
     if (index < 0) {
         LOGW("failed to post message. Target handler not registered.");
-        return;
+        return -ENOENT;
     }
 
     const HandlerInfo &info = mHandlers.valueAt(index);
@@ -91,10 +96,12 @@
              msg->target());
 
         mHandlers.removeItemsAt(index);
-        return;
+        return -ENOENT;
     }
 
     looper->post(msg, delayUs);
+
+    return OK;
 }
 
 void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
@@ -145,4 +152,38 @@
     return looper;
 }
 
+status_t ALooperRoster::postAndAwaitResponse(
+        const sp<AMessage> &msg, sp<AMessage> *response) {
+    Mutex::Autolock autoLock(mLock);
+
+    uint32_t replyID = mNextReplyID++;
+
+    msg->setInt32("replyID", replyID);
+
+    status_t err = postMessage_l(msg, 0 /* delayUs */);
+
+    if (err != OK) {
+        response->clear();
+        return err;
+    }
+
+    ssize_t index;
+    while ((index = mReplies.indexOfKey(replyID)) < 0) {
+        mRepliesCondition.wait(mLock);
+    }
+
+    *response = mReplies.valueAt(index);
+    mReplies.removeItemsAt(index);
+
+    return OK;
+}
+
+void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
+    Mutex::Autolock autoLock(mLock);
+
+    CHECK(mReplies.indexOfKey(replyID) < 0);
+    mReplies.add(replyID, reply);
+    mRepliesCondition.broadcast();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index b592c3f..582bdba 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -27,6 +27,8 @@
 
 namespace android {
 
+extern ALooperRoster gLooperRoster;
+
 AMessage::AMessage(uint32_t what, ALooper::handler_id target)
     : mWhat(what),
       mTarget(target),
@@ -227,11 +229,30 @@
 }
 
 void AMessage::post(int64_t delayUs) {
-    extern ALooperRoster gLooperRoster;
-
     gLooperRoster.postMessage(this, delayUs);
 }
 
+status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
+    return gLooperRoster.postAndAwaitResponse(this, response);
+}
+
+void AMessage::postReply(uint32_t replyID) {
+    gLooperRoster.postReply(replyID, this);
+}
+
+bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
+    int32_t tmp;
+    bool found = findInt32("replyID", &tmp);
+
+    if (!found) {
+        return false;
+    }
+
+    *replyID = static_cast<uint32_t>(tmp);
+
+    return true;
+}
+
 sp<AMessage> AMessage::dup() const {
     sp<AMessage> msg = new AMessage(mWhat, mTarget);
     msg->mNumItems = mNumItems;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 2e66a2c..ce07e32 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -136,25 +136,29 @@
 void AnotherPacketSource::queueDiscontinuity(
         ATSParser::DiscontinuityType type,
         const sp<AMessage> &extra) {
+    Mutex::Autolock autoLock(mLock);
+
+    // Leave only discontinuities in the queue.
+    List<sp<ABuffer> >::iterator it = mBuffers.begin();
+    while (it != mBuffers.end()) {
+        sp<ABuffer> oldBuffer = *it;
+
+        int32_t oldDiscontinuityType;
+        if (!oldBuffer->meta()->findInt32(
+                    "discontinuity", &oldDiscontinuityType)) {
+            it = mBuffers.erase(it);
+            continue;
+        }
+
+        ++it;
+    }
+
+    mEOSResult = OK;
+
     sp<ABuffer> buffer = new ABuffer(0);
     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
     buffer->meta()->setMessage("extra", extra);
 
-    Mutex::Autolock autoLock(mLock);
-
-#if 0
-    if (type == ATSParser::DISCONTINUITY_SEEK
-            || type == ATSParser::DISCONTINUITY_FORMATCHANGE) {
-        // XXX Fix this: This will also clear any pending discontinuities,
-        // If there's a pending DISCONTINUITY_FORMATCHANGE and the new
-        // discontinuity is "just" a DISCONTINUITY_SEEK, this will effectively
-        // downgrade the type of discontinuity received by the client.
-
-        mBuffers.clear();
-        mEOSResult = OK;
-    }
-#endif
-
     mBuffers.push_back(buffer);
     mCondition.signal();
 }
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 10cea22..7e85230 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -454,13 +454,6 @@
     EGLBoolean result = s->cnx->egl.eglDestroySurface(
             dp->disp[s->impl].dpy, s->surface);
     if (result == EGL_TRUE) {
-        ANativeWindow* const window = s->win.get();
-        if (window != NULL) {
-            native_window_set_buffers_format(window, 0);
-            if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
-                LOGE("EGLNativeWindowType %p disconnected failed", window);
-            }
-        }
         _s.terminate();
     }
     return result;
@@ -682,6 +675,9 @@
             setGLHooksThreadSpecific(&gHooksNoContext);
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
+    } else {
+        // this will LOGE the error
+        result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
     }
     return result;
 }
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 3459a8a..d2b7378 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -125,7 +125,15 @@
 
 class egl_surface_t: public egl_object_t {
 protected:
-    ~egl_surface_t() {}
+    ~egl_surface_t() {
+        ANativeWindow* const window = win.get();
+        if (window != NULL) {
+            native_window_set_buffers_format(window, 0);
+            if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
+                LOGE("EGLNativeWindowType %p disconnected failed", window);
+            }
+        }
+    }
 public:
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
@@ -232,4 +240,3 @@
 // ----------------------------------------------------------------------------
 
 #endif // ANDROID_EGL_OBJECT_H
-
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
index 5736d46..d7a591c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
deleted file mode 100644
index 31c8be7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..64b8f4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
index 37cad22..aee197c 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
deleted file mode 100644
index 739f9a6..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..1d44294
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
index 83d106d..6579ff9 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
index 1a9d88c..47f0745c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
index a6d7507..490504e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
index 1e1324a..348afb5 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
index e4e13c5..2f20d67 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..6b3ab3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..dd6651e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..d670177
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png
new file mode 100644
index 0000000..c9f0302
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png
new file mode 100644
index 0000000..dd8c498
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png
new file mode 100644
index 0000000..dc42157
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..b42b713
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index 4cb305d..16c5ca1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png
new file mode 100644
index 0000000..3e59c8d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index 85df060..c13abf0 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
index 97a07fa..3c4ce69 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 31d35c8..16ea9f6a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index 334213b..1f76128 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index 7c21c48..b7f6c11 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index 1fe6b91..a5d3c6a 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index f0cc341d..ad26f6c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index 7e8504c..39fc827 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_alarm.png
deleted file mode 100644
index 7cad385..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
new file mode 100644
index 0000000..192d4af
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
index 9e21348..d01b117 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_bg_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6db5fc4..f633825c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -63,4 +63,28 @@
 
     <!-- thickness (height) of dividers between each notification row -->
     <dimen name="notification_divider_height">1dp</dimen>
+
+    <!-- Notification drawer tuning parameters (phone UI) -->
+    <!-- Initial velocity of the shade when expanding on its own -->
+    <dimen name="self_expand_velocity">2000dp</dimen>
+    <!-- Initial velocity of the shade when collapsing on its own -->
+    <dimen name="self_collapse_velocity">2000dp</dimen>
+    <!-- Minimum final velocity of gestures interpreted as expand requests -->
+    <dimen name="fling_expand_min_velocity">200dp</dimen>
+    <!-- Minimum final velocity of gestures interpreted as collapse requests -->
+    <dimen name="fling_collapse_min_velocity">200dp</dimen>
+    <!-- Cap on contribution of x dimension of gesture to overall velocity -->
+    <dimen name="fling_gesture_max_x_velocity">200dp</dimen>
+
+    <!-- Minimum fraction of the display a gesture must travel, at any velocity, to qualify as a
+         collapse request -->
+    <item type="dimen" name="collapse_min_display_fraction">10%</item>
+    <!-- Minimum fraction of the display a gesture must travel to qualify as an expand request -->
+    <item type="dimen" name="expand_min_display_fraction">50%</item>
+
+    <!-- Initial acceleration of an expand animation after fling -->
+    <dimen name="expand_accel">2000dp</dimen>
+    <!-- Initial acceleration of an collapse animation after fling -->
+    <dimen name="collapse_accel">2000dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index c25a5b7..93ec481 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -17,8 +17,9 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default,
-         but this may be overridden on a per-locale basis if necessary. -->
-    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
+    <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date.
+         In Roman locales we now show only the date, but DOW is available for other locales if
+         necessary. -->
+    <string name="status_bar_date_formatter">%2$s</string>
 
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 5a3850d..492f3c2 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -58,7 +58,7 @@
     private static final boolean DEBUG = false;
 
     static final boolean FIXED_SIZED_SURFACE = true;
-    static final boolean USE_OPENGL = false;
+    static final boolean USE_OPENGL = true;
 
     WallpaperManager mWallpaperManager;
 
@@ -300,7 +300,9 @@
             }
 
             if (mIsHwAccelerated) {
-                drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels);
+                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                    drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+                }
             } else {
                 drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
             }
@@ -367,8 +369,8 @@
             }
         }
 
-        private void drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
-            initGL(sh);
+        private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
+            if (!initGL(sh)) return false;
 
             final float right = left + mBackgroundWidth;
             final float bottom = top + mBackgroundHeight;
@@ -423,6 +425,8 @@
             checkEglError();
     
             finishGL();
+
+            return true;
         }
 
         private FloatBuffer createMesh(int left, int top, float right, float bottom) {
@@ -533,11 +537,12 @@
         }
     
         private void finishGL() {
-            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
             mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
         }
         
-        private void initGL(SurfaceHolder surfaceHolder) {
+        private boolean initGL(SurfaceHolder surfaceHolder) {
             mEgl = (EGL10) EGLContext.getEGL();
     
             mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -565,7 +570,7 @@
                 int error = mEgl.eglGetError();
                 if (error == EGL_BAD_NATIVE_WINDOW) {
                     Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
-                    return;
+                    return false;
                 }
                 throw new RuntimeException("createWindowSurface failed " +
                         GLUtils.getEGLErrorString(error));
@@ -577,6 +582,8 @@
             }
     
             mGL = mEglContext.getGL();
+
+            return true;
         }
         
     
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index dd8e3e8..6e6567b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -112,6 +112,18 @@
     // will likely move to a resource or other tunable param at some point
     private static final int INTRUDER_ALERT_DECAY_MS = 10000;
 
+    // fling gesture tuning parameters, scaled to display density
+    private float mSelfExpandVelocityPx; // classic value: 2000px/s
+    private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+    private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+    private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+    private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+    private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+    private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+    private float mExpandAccelPx; // classic value: 2000px/s/s
+    private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -1179,7 +1191,7 @@
         }
 
         prepareTracking(0, true);
-        performFling(0, 2000.0f, true);
+        performFling(0, mSelfExpandVelocityPx, true);
     }
 
     public void animateCollapse() {
@@ -1215,7 +1227,7 @@
         // and doesn't try to re-open the windowshade.
         mExpanded = true;
         prepareTracking(y, false);
-        performFling(y, -2000.0f, true);
+        performFling(y, -mSelfCollapseVelocityPx, true);
     }
 
     void performExpand() {
@@ -1331,8 +1343,8 @@
         mTracking = true;
         mVelocityTracker = VelocityTracker.obtain();
         if (opening) {
-            mAnimAccel = 2000.0f;
-            mAnimVel = 200;
+            mAnimAccel = mExpandAccelPx;
+            mAnimVel = mFlingExpandMinVelocityPx;
             mAnimY = mStatusBarView.getHeight();
             updateExpandedViewPos((int)mAnimY);
             mAnimating = true;
@@ -1370,29 +1382,31 @@
 
         if (mExpanded) {
             if (!always && (
-                    vel > 200.0f
-                    || (y > (mDisplayMetrics.heightPixels-25) && vel > -200.0f))) {
+                    vel > mFlingCollapseMinVelocityPx
+                    || (y > (mDisplayMetrics.heightPixels*(1f-mCollapseMinDisplayFraction)) &&
+                        vel > -mFlingExpandMinVelocityPx))) {
                 // We are expanded, but they didn't move sufficiently to cause
                 // us to retract.  Animate back to the expanded position.
-                mAnimAccel = 2000.0f;
+                mAnimAccel = mExpandAccelPx;
                 if (vel < 0) {
                     mAnimVel = 0;
                 }
             }
             else {
                 // We are expanded and are now going to animate away.
-                mAnimAccel = -2000.0f;
+                mAnimAccel = -mCollapseAccelPx;
                 if (vel > 0) {
                     mAnimVel = 0;
                 }
             }
         } else {
             if (always || (
-                    vel > 200.0f
-                    || (y > (mDisplayMetrics.heightPixels/2) && vel > -200.0f))) {
+                    vel > mFlingExpandMinVelocityPx
+                    || (y > (mDisplayMetrics.heightPixels*(1f-mExpandMinDisplayFraction)) &&
+                        vel > -mFlingCollapseMinVelocityPx))) {
                 // We are collapsed, and they moved enough to allow us to
                 // expand.  Animate in the notifications.
-                mAnimAccel = 2000.0f;
+                mAnimAccel = mExpandAccelPx;
                 if (vel < 0) {
                     mAnimVel = 0;
                 }
@@ -1400,7 +1414,7 @@
             else {
                 // We are collapsed, but they didn't move sufficiently to cause
                 // us to retract.  Animate back to the collapsed position.
-                mAnimAccel = -2000.0f;
+                mAnimAccel = -mCollapseAccelPx;
                 if (vel > 0) {
                     mAnimVel = 0;
                 }
@@ -1480,8 +1494,8 @@
                 if (xVel < 0) {
                     xVel = -xVel;
                 }
-                if (xVel > 150.0f) {
-                    xVel = 150.0f; // limit how much we care about the x axis
+                if (xVel > mFlingGestureMaxXVelocityPx) {
+                    xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
                 }
 
                 float vel = (float)Math.hypot(yVel, xVel);
@@ -1489,6 +1503,14 @@
                     vel = -vel;
                 }
 
+                if (CHATTY) {
+                    Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f", 
+                        mVelocityTracker.getXVelocity(), 
+                        mVelocityTracker.getYVelocity(),
+                        xVel, yVel,
+                        vel));
+                }
+
                 performFling((int)event.getRawY(), vel, false);
             }
 
@@ -2133,6 +2155,19 @@
 
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
 
+        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+
         if (false) Slog.v(TAG, "updateResources");
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 322a8c8..ee270f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -161,7 +161,7 @@
         mService.setIconVisibility("bluetooth", mBluetoothEnabled);
 
         // Alarm clock
-        mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null);
+        mService.setIcon("alarm_clock", R.drawable.stat_sys_alarm, 0, null);
         mService.setIconVisibility("alarm_clock", false);
 
         // Sync state
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index a171514..d3f9525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -91,7 +91,7 @@
         final Context context = getContext();
         Date now = new Date();
         CharSequence dow = DateFormat.format("EEEE", now);
-        CharSequence date = DateFormat.getMediumDateFormat(getContext()).format(now);
+        CharSequence date = DateFormat.getLongDateFormat(context).format(now);
         setText(context.getString(R.string.status_bar_date_formatter, dow, date));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index dd59667..2ab667d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -879,12 +879,11 @@
             removeNotificationViews(key);
             addNotificationViews(key, notification);
         }
-        // fullScreenIntent doesn't happen on updates.  You need to clear & repost a new
-        // notification.
-        final boolean immersive = isImmersive();
-        if (false && immersive) {
-            // TODO: immersive mode
-        } else {
+
+        // Restart the ticker if it's still running
+        if (notification.notification.tickerText != null
+                && !TextUtils.equals(notification.notification.tickerText,
+                    oldEntry.notification.notification.tickerText)) {
             tick(key, notification, false);
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index be129a8..dfd1b00 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -124,6 +124,7 @@
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
 import android.view.KeyCharacterMap.FallbackAction;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.media.IAudioService;
@@ -3104,7 +3105,29 @@
         mHandler.post(new Runnable() {
             @Override public void run() {
                 if (mBootMsgDialog == null) {
-                    mBootMsgDialog = new ProgressDialog(mContext);
+                    mBootMsgDialog = new ProgressDialog(mContext) {
+                        // This dialog will consume all events coming in to
+                        // it, to avoid it trying to do things too early in boot.
+                        @Override public boolean dispatchKeyEvent(KeyEvent event) {
+                            return true;
+                        }
+                        @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+                            return true;
+                        }
+                        @Override public boolean dispatchTouchEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+                            return true;
+                        }
+                        @Override public boolean dispatchPopulateAccessibilityEvent(
+                                AccessibilityEvent event) {
+                            return true;
+                        }
+                    };
                     mBootMsgDialog.setTitle(R.string.android_upgrading_title);
                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                     mBootMsgDialog.setIndeterminate(true);
diff --git a/preloaded-classes b/preloaded-classes
index 1b2bfd5..31d49ce 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -324,7 +324,6 @@
 android.ddm.DdmHandleThread
 android.ddm.DdmRegister
 android.debug.JNITest
-android.drm.DrmManagerClient
 android.emoji.EmojiFactory
 android.graphics.AvoidXfermode
 android.graphics.Bitmap
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 5e54d61..5ffcdc5 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -764,12 +764,18 @@
         
         public void scheduleTimeTickEvent() {
             Calendar calendar = Calendar.getInstance();
-            calendar.setTimeInMillis(System.currentTimeMillis());
+            final long currentTime = System.currentTimeMillis();
+            calendar.setTimeInMillis(currentTime);
             calendar.add(Calendar.MINUTE, 1);
             calendar.set(Calendar.SECOND, 0);
             calendar.set(Calendar.MILLISECOND, 0);
-      
-            set(AlarmManager.RTC, calendar.getTimeInMillis(), mTimeTickSender);
+
+            // Schedule this event for the amount of time that it would take to get to
+            // the top of the next minute.
+            final long tickEventDelay = calendar.getTimeInMillis() - currentTime;
+
+            set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay,
+                    mTimeTickSender);
         }
 	
         public void scheduleDateChangedEvent() {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c11755b..38bcebc 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -2018,8 +2018,9 @@
         if (DEBUG) Slog.v(TAG, "Show switching menu");
 
         final Context context = mContext;
-
         final PackageManager pm = context.getPackageManager();
+        final boolean isScreenLocked = mKeyguardManager != null
+                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
 
         String lastInputMethodId = Settings.Secure.getString(context
                 .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -2075,7 +2076,7 @@
                         final String subtypeHashCode = String.valueOf(subtype.hashCode());
                         // We show all enabled IMEs and subtypes when an IME is shown.
                         if (enabledSubtypeSet.contains(subtypeHashCode)
-                                && (mInputShown || !subtype.isAuxiliary())) {
+                                && ((mInputShown && !isScreenLocked) || !subtype.isAuxiliary())) {
                             final CharSequence title;
                             final String mode = subtype.getMode();
                             title = TextUtils.concat(subtype.getDisplayName(context,
@@ -2162,8 +2163,7 @@
                         }
                     });
 
-            if (showSubtypes && mKeyguardManager != null && !(mKeyguardManager.isKeyguardLocked()
-                    && mKeyguardManager.isKeyguardSecure())) {
+            if (showSubtypes && !isScreenLocked) {
                 mDialogBuilder.setPositiveButton(
                         com.android.internal.R.string.configure_input_methods,
                         new DialogInterface.OnClickListener() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e6f92a5..d0e8b5e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -182,7 +182,7 @@
 
             // only initialize the power service after we have started the
             // lights service, content providers and the battery service.
-            power.init(context, lights, ActivityManagerService.getDefault(), battery);
+            power.init(context, lights, ActivityManagerService.self(), battery);
 
             Slog.i(TAG, "Alarm Manager");
             alarm = new AlarmManagerService(context);
@@ -197,8 +197,7 @@
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
 
-            ((ActivityManagerService)ServiceManager.getService("activity"))
-                    .setWindowManager(wm);
+            ActivityManagerService.self().setWindowManager(wm);
 
             // Skip Bluetooth if we have an emulator kernel
             // TODO: Use a more reliable check to see if this product should
@@ -265,7 +264,7 @@
         } catch (Throwable e) {
             reportWtf("making display ready", e);
         }
- 
+
         try {
             pm.performBootDexOpt();
         } catch (Throwable e) {
@@ -618,8 +617,7 @@
         // where third party code can really run (but before it has actually
         // started launching the initial applications), for us to complete our
         // initialization.
-        ((ActivityManagerService)ActivityManagerNative.getDefault())
-                .systemReady(new Runnable() {
+        ActivityManagerService.self().systemReady(new Runnable() {
             public void run() {
                 Slog.i(TAG, "Making services ready");
 
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index dd54c16..4447ad0 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -421,11 +421,13 @@
                 modified = true;
             }
             if (modified) {
-                Slog.d(TAG, "onDataConnectionStateChanged(" + state + ", " + networkType + ")");
+                Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState
+                        + ", " + mDataConnectionNetworkType + ")");
                 for (Record r : mRecords) {
                     if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
                         try {
-                            r.callback.onDataConnectionStateChanged(state, networkType);
+                            r.callback.onDataConnectionStateChanged(mDataConnectionState,
+                                    mDataConnectionNetworkType);
                         } catch (RemoteException ex) {
                             mRemoveList.add(r.binder);
                         }
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index 321274f..f6c369e 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -131,6 +131,11 @@
             if (DBG) Slog.d(TAG, "Add: " + compName);
             try {
                 final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri);
+                if (sci.getSubtypeCount() <= 0) {
+                    Slog.w(TAG, "Skipping text service " + compName
+                            + ": it does not contain subtypes.");
+                    continue;
+                }
                 list.add(sci);
                 map.put(sci.getId(), sci);
             } catch (XmlPullParserException e) {
@@ -186,9 +191,11 @@
         }
     }
 
+    // TODO: Respect allowImplicitlySelectedSubtype
     // TODO: Save SpellCheckerSubtype by supported languages.
     @Override
-    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale) {
+    public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
+            String locale, boolean allowImplicitlySelectedSubtype) {
         synchronized (mSpellCheckerMap) {
             final String subtypeHashCodeStr =
                     Settings.Secure.getString(mContext.getContentResolver(),
@@ -203,27 +210,40 @@
                 }
                 return null;
             }
-            if (TextUtils.isEmpty(subtypeHashCodeStr)) {
-                if (DBG) {
-                    Slog.w(TAG, "Return first subtype in " + sci.getId());
-                }
-                // Return the first Subtype if there is no settings for the current subtype.
-                return sci.getSubtypeAt(0);
+            final int hashCode;
+            if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
+                hashCode = Integer.valueOf(subtypeHashCodeStr);
+            } else {
+                hashCode = 0;
             }
-            final int hashCode = Integer.valueOf(subtypeHashCodeStr);
+            if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+                return null;
+            }
+            final String systemLocale =
+                    mContext.getResources().getConfiguration().locale.toString();
+            SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-                if (scs.hashCode() == hashCode) {
+                if (hashCode == 0) {
+                    if (systemLocale.equals(locale)) {
+                        return scs;
+                    } else if (candidate == null) {
+                        final String scsLocale = scs.getLocale();
+                        if (systemLocale.length() >= 2
+                                && scsLocale.length() >= 2
+                                && systemLocale.substring(0, 2).equals(
+                                        scsLocale.substring(0, 2))) {
+                            candidate = scs;
+                        }
+                    }
+                } else if (scs.hashCode() == hashCode) {
                     if (DBG) {
                         Slog.w(TAG, "Return subtype " + scs.hashCode());
                     }
                     return scs;
                 }
             }
-            if (DBG) {
-                Slog.w(TAG, "Return first subtype in " + sci.getId());
-            }
-            return sci.getSubtypeAt(0);
+            return candidate;
         }
     }
 
@@ -396,10 +416,16 @@
             Slog.w(TAG, "setCurrentSpellChecker: " + sciId);
         }
         if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return;
+        final SpellCheckerInfo currentSci = getCurrentSpellChecker(null);
+        if (currentSci != null && currentSci.getId().equals(sciId)) {
+            // Do nothing if the current spell checker is same as new spell checker.
+            return;
+        }
         final long ident = Binder.clearCallingIdentity();
         try {
             Settings.Secure.putString(mContext.getContentResolver(),
                     Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            setCurrentSpellCheckerSubtypeLocked(0);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -410,21 +436,17 @@
             Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode);
         }
         final SpellCheckerInfo sci = getCurrentSpellChecker(null);
-        if (sci == null) return;
-        boolean found = false;
-        for (int i = 0; i < sci.getSubtypeCount(); ++i) {
+        int tempHashCode = 0;
+        for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) {
             if(sci.getSubtypeAt(i).hashCode() == hashCode) {
-                found = true;
+                tempHashCode = hashCode;
                 break;
             }
         }
-        if (!found) {
-            return;
-        }
         final long ident = Binder.clearCallingIdentity();
         try {
             Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+                    Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode));
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7232a94..bb5e989 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -91,7 +91,6 @@
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.IPermissionController;
 import android.os.Looper;
@@ -5518,6 +5517,48 @@
         return msg;
     }
 
+    boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
+        if (r != null) {
+            Integer cnt = r.conProviders.get(cpr);
+            if (DEBUG_PROVIDER) Slog.v(TAG,
+                    "Adding provider requested by "
+                    + r.processName + " from process "
+                    + cpr.info.processName + ": " + cpr.name.flattenToShortString()
+                    + " cnt=" + (cnt == null ? 1 : cnt));
+            if (cnt == null) {
+                cpr.clients.add(r);
+                r.conProviders.put(cpr, new Integer(1));
+                return true;
+            } else {
+                r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
+            }
+        } else {
+            cpr.externals++;
+        }
+        return false;
+    }
+
+    boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
+        if (r != null) {
+            Integer cnt = r.conProviders.get(cpr);
+            if (DEBUG_PROVIDER) Slog.v(TAG,
+                    "Removing provider requested by "
+                    + r.processName + " from process "
+                    + cpr.info.processName + ": " + cpr.name.flattenToShortString()
+                    + " cnt=" + cnt);
+            if (cnt == null || cnt.intValue() <= 1) {
+                cpr.clients.remove(r);
+                r.conProviders.remove(cpr);
+                return true;
+            } else {
+                r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
+            }
+        } else {
+            cpr.externals++;
+        }
+        return false;
+    }
+
     private final ContentProviderHolder getContentProviderImpl(
         IApplicationThread caller, String name) {
         ContentProviderRecord cpr;
@@ -5537,7 +5578,8 @@
 
             // First check if this content provider has been published...
             cpr = mProvidersByName.get(name);
-            if (cpr != null) {
+            boolean providerRunning = cpr != null;
+            if (providerRunning) {
                 cpi = cpr.info;
                 String msg;
                 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
@@ -5561,18 +5603,8 @@
 
                 // In this case the provider instance already exists, so we can
                 // return it right away.
-                if (r != null) {
-                    if (DEBUG_PROVIDER) Slog.v(TAG,
-                            "Adding provider requested by "
-                            + r.processName + " from process "
-                            + cpr.info.processName);
-                    Integer cnt = r.conProviders.get(cpr);
-                    if (cnt == null) {
-                        r.conProviders.put(cpr, new Integer(1));
-                    } else {
-                        r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
-                    }
-                    cpr.clients.add(r);
+                final boolean countChanged = incProviderCount(r, cpr);
+                if (countChanged) {
                     if (cpr.app != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                         // If this is a perceptible app accessing the provider,
                         // make sure to count it as being accessed and thus
@@ -5580,17 +5612,46 @@
                         // content providers are often expensive to start.
                         updateLruProcessLocked(cpr.app, false, true);
                     }
-                } else {
-                    cpr.externals++;
                 }
 
                 if (cpr.app != null) {
-                    updateOomAdjLocked(cpr.app);
+                    if (false) {
+                        if (cpr.name.flattenToShortString().equals(
+                                "com.android.providers.calendar/.CalendarProvider2")) {
+                            Slog.v(TAG, "****************** KILLING "
+                                + cpr.name.flattenToShortString());
+                            Process.killProcess(cpr.app.pid);
+                        }
+                    }
+                    boolean success = updateOomAdjLocked(cpr.app);
+                    if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
+                    // NOTE: there is still a race here where a signal could be
+                    // pending on the process even though we managed to update its
+                    // adj level.  Not sure what to do about this, but at least
+                    // the race is now smaller.
+                    if (!success) {
+                        // Uh oh...  it looks like the provider's process
+                        // has been killed on us.  We need to wait for a new
+                        // process to be started, and make sure its death
+                        // doesn't kill our process.
+                        Slog.i(TAG,
+                                "Existing provider " + cpr.name.flattenToShortString()
+                                + " is crashing; detaching " + r);
+                        boolean lastRef = decProviderCount(r, cpr);
+                        appDiedLocked(cpr.app, cpr.app.pid, cpr.app.thread);
+                        if (!lastRef) {
+                            // This wasn't the last ref our process had on
+                            // the provider...  we have now been killed, bail.
+                            return null;
+                        }
+                        providerRunning = false;
+                    }
                 }
 
                 Binder.restoreCallingIdentity(origId);
+            }
 
-            } else {
+            if (!providerRunning) {
                 try {
                     cpi = AppGlobals.getPackageManager().
                         resolveContentProvider(name,
@@ -5701,22 +5762,7 @@
                     mProvidersByClass.put(comp, cpr);
                 }
                 mProvidersByName.put(name, cpr);
-
-                if (r != null) {
-                    if (DEBUG_PROVIDER) Slog.v(TAG,
-                            "Adding provider requested by "
-                            + r.processName + " from process "
-                            + cpr.info.processName);
-                    Integer cnt = r.conProviders.get(cpr);
-                    if (cnt == null) {
-                        r.conProviders.put(cpr, new Integer(1));
-                    } else {
-                        r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
-                    }
-                    cpr.clients.add(r);
-                } else {
-                    cpr.externals++;
-                }
+                incProviderCount(r, cpr);
             }
         }
 
@@ -5780,24 +5826,16 @@
             //update content provider record entry info
             ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
             ContentProviderRecord localCpr = mProvidersByClass.get(comp);
-            if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
-                    + r.info.processName + " from process "
-                    + localCpr.appInfo.processName);
             if (localCpr.app == r) {
                 //should not happen. taken care of as a local provider
                 Slog.w(TAG, "removeContentProvider called on local provider: "
                         + cpr.info.name + " in process " + r.processName);
                 return;
             } else {
-                Integer cnt = r.conProviders.get(localCpr);
-                if (cnt == null || cnt.intValue() <= 1) {
-                    localCpr.clients.remove(r);
-                    r.conProviders.remove(localCpr);
-                } else {
-                    r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
+                if (decProviderCount(r, localCpr)) {
+                    updateOomAdjLocked();
                 }
             }
-            updateOomAdjLocked();
         }
     }
 
@@ -13458,16 +13496,18 @@
         }
     }
 
-    private final void updateOomAdjLocked(
+    private final boolean updateOomAdjLocked(
             ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
         app.hiddenAdj = hiddenAdj;
 
         if (app.thread == null) {
-            return;
+            return false;
         }
 
         final boolean wasKeeping = app.keeping;
 
+        boolean success = true;
+
         computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
 
         if (app.curRawAdj != app.setRawAdj) {
@@ -13504,6 +13544,7 @@
                     " oom adj to " + app.curAdj + " because " + app.adjType);
                 app.setAdj = app.curAdj;
             } else {
+                success = false;
                 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
             }
         }
@@ -13518,6 +13559,7 @@
                 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
                         app.processName, app.setAdj, app.waitingToKill);
                 Process.killProcessQuiet(app.pid);
+                success = false;
             } else {
                 if (true) {
                     long oldId = Binder.clearCallingIdentity();
@@ -13540,6 +13582,7 @@
                 }
             }
         }
+        return success;
     }
 
     private final ActivityRecord resumedAppLocked() {
@@ -13553,7 +13596,7 @@
         return resumedActivity;
     }
 
-    private final void updateOomAdjLocked(ProcessRecord app) {
+    private final boolean updateOomAdjLocked(ProcessRecord app) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         int curAdj = app.curAdj;
@@ -13562,7 +13605,7 @@
 
         mAdjSeq++;
 
-        updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
+        boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
         final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
             && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
         if (nowHidden != wasHidden) {
@@ -13570,6 +13613,7 @@
             // list may also be changed.
             updateOomAdjLocked();
         }
+        return success;
     }
 
     final void updateOomAdjLocked() {
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index dfcc0bfa..131255f 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -163,7 +163,7 @@
         int minSize = 320*480;  //  153600
         int maxSize = 1280*800; // 1024000  230400 870400  .264
         float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
-        Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);
+        //Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);
 
         StringBuilder adjString = new StringBuilder();
         StringBuilder memString = new StringBuilder();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6fde361..598220f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2211,10 +2211,13 @@
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; ++i) {
         const sp<LayerBase>& layer(layers[i]);
-        const uint32_t z = layer->drawingState().z;
-        if (z >= minLayerZ && z <= maxLayerZ) {
-            if (layer->isProtected()) {
-                return INVALID_OPERATION;
+        const uint32_t flags = layer->drawingState().flags;
+        if (!(flags & ISurfaceComposer::eLayerHidden)) {
+            const uint32_t z = layer->drawingState().z;
+            if (z >= minLayerZ && z <= maxLayerZ) {
+                if (layer->isProtected()) {
+                    return INVALID_OPERATION;
+                }
             }
         }
     }
@@ -2270,9 +2273,12 @@
 
         for (size_t i=0 ; i<count ; ++i) {
             const sp<LayerBase>& layer(layers[i]);
-            const uint32_t z = layer->drawingState().z;
-            if (z >= minLayerZ && z <= maxLayerZ) {
-                layer->drawForSreenShot();
+            const uint32_t flags = layer->drawingState().flags;
+            if (!(flags & ISurfaceComposer::eLayerHidden)) {
+                const uint32_t z = layer->drawingState().z;
+                if (z >= minLayerZ && z <= maxLayerZ) {
+                    layer->drawForSreenShot();
+                }
             }
         }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 2cf4b88..0aed77e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -545,7 +545,7 @@
             int defaultRoamingIndicator = 0;  //[12] Is default roaming indicator from PRL
             int reasonForDenial = 0;       //[13] Denial reason if registrationState = 3
 
-            if (states.length == 14) {
+            if (states.length >= 14) {
                 try {
                     if (states[0] != null) {
                         registrationState = Integer.parseInt(states[0]);
@@ -593,8 +593,8 @@
                 }
             } else {
                 throw new RuntimeException("Warning! Wrong number of parameters returned from "
-                                     + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
-                                     + states.length);
+                                     + "RIL_REQUEST_REGISTRATION_STATE: expected 14 or more "
+                                     + "strings and got " + states.length + " strings");
             }
 
             mRegistrationState = registrationState;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index c8671c1..00fb0e0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -576,7 +576,8 @@
         boolean allowed =
                     (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
                     mPhone.mIccRecords.getRecordsLoaded() &&
-                    mPhone.getState() == Phone.State.IDLE &&
+                    (mPhone.getState() == Phone.State.IDLE ||
+                     mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) &&
                     internalDataEnabled &&
                     (!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
                     !mIsPsRestricted &&
@@ -587,8 +588,10 @@
                 reason += " - gprs= " + gprsState;
             }
             if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded";
-            if (mPhone.getState() != Phone.State.IDLE) {
+            if (mPhone.getState() != Phone.State.IDLE &&
+                    !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                 reason += " - PhoneState= " + mPhone.getState();
+                reason += " - Concurrent voice and data not allowed";
             }
             if (!internalDataEnabled) reason += " - mInternalDataEnabled= false";
             if (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()) {
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index 8a27213..f503658 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -27,11 +27,18 @@
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content">
 
-            <Button android:id="@+id/button"
+            <TextView android:id="@+id/textview_password_default"
                     android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button_text"
                     android:textSize="32dip"
+                    android:text="@string/textview_password_default_text"
+            />
+
+            <EditText android:id="@+id/edittext_password_default"
+                      android:layout_height="wrap_content"
+                      android:layout_width="match_parent"
+                      android:textSize="32dip"
+                      android:password="true"
                     />
 
             <TextView android:id="@+id/textview_default"
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index b0809da..b1f5e50e 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -28,6 +28,7 @@
     <string name="textview_ltr_text">This is a text for a LTR TextView</string>
     <string name="textview_rtl_text">This is a text for a RTL TextView</string>
     <string name="textview_default_text">This is a text for a default TextView</string>
+    <string name="textview_password_default_text">This is a text for a password TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
     <string name="normal_text">Normal String</string>
     <string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 5b4bce2..83dda5c 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -281,7 +281,11 @@
         if (WifiNative.removeNetworkCommand(netId)) {
             WifiNative.saveConfigCommand();
             synchronized (sConfiguredNetworks) {
-                sConfiguredNetworks.remove(netId);
+                WifiConfiguration config = sConfiguredNetworks.get(netId);
+                if (config != null) {
+                    sConfiguredNetworks.remove(netId);
+                    sNetworkIds.remove(configKey(config));
+                }
             }
             writeIpAndProxyConfigurations();
             sendConfiguredNetworksChangedBroadcast();
@@ -315,7 +319,13 @@
     static boolean removeNetwork(int netId) {
         boolean ret = WifiNative.removeNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
-            if (ret) sConfiguredNetworks.remove(netId);
+            if (ret) {
+                WifiConfiguration config = sConfiguredNetworks.get(netId);
+                if (config != null) {
+                    sConfiguredNetworks.remove(netId);
+                    sNetworkIds.remove(configKey(config));
+                }
+            }
         }
         sendConfiguredNetworksChangedBroadcast();
         return ret;
@@ -366,7 +376,8 @@
         boolean ret = WifiNative.disableNetworkCommand(netId);
         synchronized (sConfiguredNetworks) {
             WifiConfiguration config = sConfiguredNetworks.get(netId);
-            if (config != null) {
+            /* Only change the reason if the network was not previously disabled */
+            if (config != null && config.status != Status.DISABLED) {
                 config.status = Status.DISABLED;
                 config.disableReason = reason;
             }
@@ -600,7 +611,10 @@
         synchronized (sConfiguredNetworks) {
             for(WifiConfiguration config : sConfiguredNetworks.values()) {
                 if(config != null && config.networkId != netId) {
-                    config.status = Status.DISABLED;
+                    if (config.status != Status.DISABLED) {
+                        config.status = Status.DISABLED;
+                        config.disableReason = WifiConfiguration.DISABLED_UNKNOWN_REASON;
+                    }
                 }
             }
         }
@@ -854,18 +868,24 @@
          * refer to an existing configuration.
          */
         int netId = config.networkId;
-        boolean updateFailed = true;
+        boolean newNetwork = false;
         // networkId of INVALID_NETWORK_ID means we want to create a new network
-        boolean newNetwork = (netId == INVALID_NETWORK_ID);
-
-        if (newNetwork) {
-            netId = WifiNative.addNetworkCommand();
-            if (netId < 0) {
-                Log.e(TAG, "Failed to add a network!");
-                return new NetworkUpdateResult(INVALID_NETWORK_ID);
-          }
+        if (netId == INVALID_NETWORK_ID) {
+            Integer savedNetId = sNetworkIds.get(configKey(config));
+            if (savedNetId != null) {
+                netId = savedNetId;
+            } else {
+                newNetwork = true;
+                netId = WifiNative.addNetworkCommand();
+                if (netId < 0) {
+                    Log.e(TAG, "Failed to add a network!");
+                    return new NetworkUpdateResult(INVALID_NETWORK_ID);
+                }
+            }
         }
 
+        boolean updateFailed = true;
+
         setVariables: {
 
             if (config.SSID != null &&
@@ -1053,12 +1073,15 @@
         if (sConfig == null) {
             sConfig = new WifiConfiguration();
             sConfig.networkId = netId;
-            synchronized (sConfiguredNetworks) {
-                sConfiguredNetworks.put(netId, sConfig);
-            }
         }
+
         readNetworkVariables(sConfig);
 
+        synchronized (sConfiguredNetworks) {
+            sConfiguredNetworks.put(netId, sConfig);
+            sNetworkIds.put(configKey(sConfig), netId);
+        }
+
         NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(sConfig, config);
         result.setNetworkId(netId);
         return result;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d2a0b30..85a6f27 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -530,6 +530,7 @@
         if (source != null) {
             networkId = source.networkId;
             status = source.status;
+            disableReason = source.disableReason;
             SSID = source.SSID;
             BSSID = source.BSSID;
             preSharedKey = source.preSharedKey;
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 6c6f149..c1f6785 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -243,7 +243,7 @@
 
     /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
         [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
-    public static String p2pConnect(WifiP2pConfig config) {
+    public static String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
         if (config == null) return null;
         List<String> args = new ArrayList<String>();
         WpsConfiguration wpsConfig = config.wpsConfig;
@@ -269,15 +269,15 @@
                 break;
         }
 
-        if (config.isPersistent) args.add("persistent");
-        if (config.joinExistingGroup) args.add("join");
+        /* Persist unless there is an explicit request to not do so*/
+        if (config.persist != WifiP2pConfig.Persist.NO) args.add("persistent");
+        if (joinExistingGroup) args.add("join");
 
         int groupOwnerIntent = config.groupOwnerIntent;
         if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
             groupOwnerIntent = 3; //default value
         }
         args.add("go_intent=" + groupOwnerIntent);
-        if (config.channel > 0) args.add("freq=" + config.channel);
 
         String command = "P2P_CONNECT ";
         for (String s : args) command += s + " ";
@@ -300,11 +300,24 @@
 
     /* Invite a peer to a group */
     public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
-        if (group == null || deviceAddress == null) return false;
-        return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
-                + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
+        if (deviceAddress == null) return false;
+
+        if (group == null) {
+            return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
+        } else {
+            return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
+                    + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
+        }
     }
 
+    /* Reinvoke a persistent connection */
+    public static boolean p2pReinvoke(int netId, String deviceAddress) {
+        if (deviceAddress == null || netId < 0) return false;
+
+        return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
+    }
+
+
     public static String p2pGetInterfaceAddress(String deviceAddress) {
         if (deviceAddress == null) return null;
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index b77fd76..2d57363 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -51,14 +51,16 @@
      */
     public int groupOwnerIntent = -1;
 
-    public boolean isPersistent;
-
-    public boolean joinExistingGroup;
-
     /**
-     * Channel frequency in MHz
+     * Indicates whether the configuration is saved
      */
-    public int channel;
+    public enum Persist {
+        SYSTEM_DEFAULT,
+        YES,
+        NO
+    }
+
+    public Persist persist = Persist.SYSTEM_DEFAULT;
 
     public WifiP2pConfig() {
         //set defaults
@@ -112,9 +114,7 @@
         sbuf.append("\n address: ").append(deviceAddress);
         sbuf.append("\n wps: ").append(wpsConfig);
         sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
-        sbuf.append("\n isPersistent: ").append(isPersistent);
-        sbuf.append("\n joinExistingGroup: ").append(joinExistingGroup);
-        sbuf.append("\n channel: ").append(channel);
+        sbuf.append("\n persist: ").append(persist.toString());
         return sbuf.toString();
     }
 
@@ -136,9 +136,7 @@
         dest.writeString(deviceAddress);
         dest.writeParcelable(wpsConfig, flags);
         dest.writeInt(groupOwnerIntent);
-        dest.writeInt(isPersistent ? 1 : 0);
-        dest.writeInt(joinExistingGroup ? 1 : 0);
-        dest.writeInt(channel);
+        dest.writeString(persist.name());
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -150,9 +148,7 @@
                 config.deviceAddress = in.readString();
                 config.wpsConfig = (WpsConfiguration) in.readParcelable(null);
                 config.groupOwnerIntent = in.readInt();
-                config.isPersistent = (in.readInt() == 1);
-                config.joinExistingGroup = (in.readInt() == 1);
-                config.channel = in.readInt();
+                config.persist = Persist.valueOf(in.readString());
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 4ec23b8..50f624a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -51,8 +51,10 @@
         }
     }
 
-    public void clear() {
+    public boolean clear() {
+        if (mDevices.isEmpty()) return false;
         mDevices.clear();
+        return true;
     }
 
     public void add(WifiP2pDevice device) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
similarity index 95%
rename from wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
rename to wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
index 7bab5d3..a347148 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.aidl
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.p2p;
 
-parcelable WifiP2pStatus;
+parcelable WifiP2pInfo;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
new file mode 100644
index 0000000..9dc2fbf
--- /dev/null
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * A class representing connection info on Wi-fi P2p
+ * @hide
+ */
+public class WifiP2pInfo implements Parcelable {
+
+    public boolean groupFormed;
+
+    public boolean isGroupOwner;
+
+    public InetAddress groupOwnerAddress;
+
+    public WifiP2pInfo() {
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append("groupFormed: ").append(groupFormed)
+            .append("isGroupOwner: ").append(isGroupOwner)
+            .append("groupOwnerAddress: ").append(groupOwnerAddress);
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    public WifiP2pInfo(WifiP2pInfo source) {
+        if (source != null) {
+            groupFormed = source.groupFormed;
+            isGroupOwner = source.isGroupOwner;
+            groupOwnerAddress = source.groupOwnerAddress;
+       }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByte(groupFormed ? (byte)1 : (byte)0);
+        dest.writeByte(isGroupOwner ? (byte)1 : (byte)0);
+
+        if (groupOwnerAddress != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(groupOwnerAddress.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiP2pInfo> CREATOR =
+        new Creator<WifiP2pInfo>() {
+            public WifiP2pInfo createFromParcel(Parcel in) {
+                WifiP2pInfo info = new WifiP2pInfo();
+                info.groupFormed = (in.readByte() == 1);
+                info.isGroupOwner = (in.readByte() == 1);
+                if (in.readByte() == 1) {
+                    try {
+                        info.groupOwnerAddress = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
+                return info;
+            }
+
+            public WifiP2pInfo[] newArray(int size) {
+                return new WifiP2pInfo[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index cc1f062..25daf1c 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -95,6 +95,12 @@
         "android.net.wifi.CONNECTION_STATE_CHANGE";
 
     /**
+     * The lookup key for a {@link android.net.wifi.p2p.WifiP2pInfo} object
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     */
+    public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
+
+    /**
      * The lookup key for a {@link android.net.NetworkInfo} object associated with the
      * Wi-Fi network. Retrieve with
      * {@link android.content.Intent#getParcelableExtra(String)}.
@@ -145,57 +151,38 @@
     public static final int ENABLE_P2P_FAILED                       = BASE + 2;
     public static final int ENABLE_P2P_SUCCEEDED                    = BASE + 3;
 
-    /* arg1 on ENABLE_P2P_FAILED indicates a reason for failure */
+    public static final int DISABLE_P2P                             = BASE + 4;
+    public static final int DISABLE_P2P_FAILED                      = BASE + 5;
+    public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 6;
+
+    public static final int DISCOVER_PEERS                          = BASE + 7;
+    public static final int DISCOVER_PEERS_FAILED                   = BASE + 8;
+    public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 9;
+
+    public static final int CONNECT                                 = BASE + 10;
+    public static final int CONNECT_FAILED                          = BASE + 11;
+    public static final int CONNECT_SUCCEEDED                       = BASE + 12;
+
+    public static final int CREATE_GROUP                            = BASE + 13;
+    public static final int CREATE_GROUP_FAILED                     = BASE + 14;
+    public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
+
+    public static final int REMOVE_GROUP                            = BASE + 16;
+    public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
+    public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
+
+    public static final int REQUEST_PEERS                           = BASE + 19;
+    public static final int RESPONSE_PEERS                          = BASE + 20;
+
+    public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
+    public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
+
+    /* arg1 values on response messages from the framework */
     public static final int P2P_UNSUPPORTED     = 1;
 
-    public static final int DISABLE_P2P                             = BASE + 5;
-    public static final int DISABLE_P2P_FAILED                      = BASE + 6;
-    public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 7;
-
-    public static final int START_LISTEN_MODE                       = BASE + 9;
-    public static final int START_LISTEN_FAILED                     = BASE + 10;
-    public static final int START_LISTEN_SUCCEEDED                  = BASE + 11;
-
-    public static final int DISCOVER_PEERS                          = BASE + 13;
-    public static final int DISCOVER_PEERS_FAILED                   = BASE + 14;
-    public static final int DISCOVER_PEERS_SUCCEDED                 = BASE + 15;
-
-    public static final int CANCEL_DISCOVER_PEERS                   = BASE + 17;
-    public static final int CANCEL_DISCOVER_PEERS_FAILED            = BASE + 18;
-    public static final int CANCEL_DISCOVER_PEERS_SUCCEDED          = BASE + 19;
-
-    public static final int CONNECT                                 = BASE + 21;
-    public static final int CONNECT_FAILED                          = BASE + 22;
-    public static final int CONNECT_SUCCEEDED                       = BASE + 23;
-
-    public static final int CANCEL_CONNECT                          = BASE + 25;
-    public static final int CANCEL_CONNECT_FAILED                   = BASE + 26;
-    public static final int CANCEL_CONNECT_SUCCEDED                 = BASE + 27;
-
-    public static final int REJECT                                  = BASE + 28;
-    public static final int REJECT_FAILED                           = BASE + 29;
-    public static final int REJECT_SUCCEEDED                        = BASE + 30;
-
-    public static final int CREATE_GROUP                            = BASE + 31;
-    public static final int CREATE_GROUP_FAILED                     = BASE + 32;
-    public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 33;
-
-    public static final int REMOVE_GROUP                            = BASE + 34;
-    public static final int REMOVE_GROUP_FAILED                     = BASE + 35;
-    public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 36;
-
-    public static final int REQUEST_SETTINGS                        = BASE + 37;
-    public static final int RESPONSE_SETTINGS                       = BASE + 38;
-
-    public static final int REQUEST_PEERS                           = BASE + 39;
-    public static final int RESPONSE_PEERS                          = BASE + 40;
-
-    public static final int REQUEST_CONNECTION_STATUS               = BASE + 41;
-    public static final int RESPONSE_CONNECTION_STATUS              = BASE + 42;
-
-    public static final int WPS_PBC                                 = BASE + 43;
-    public static final int WPS_PIN                                 = BASE + 44;
-    public static final int WPS_PIN_AVAILABLE                       = BASE + 45;
+    public static final int WPS_PBC                                 = BASE + 23;
+    public static final int WPS_PIN                                 = BASE + 24;
+    public static final int WPS_PIN_AVAILABLE                       = BASE + 25;
 
     /**
      * Create a new WifiP2pManager instance. Applications use
@@ -269,17 +256,6 @@
     }
 
     /**
-     * Set device in listen mode. This will make the device discoverable by
-     * another peer.
-     * A dialog to the user is thrown to request his permission since it can
-     * have a significant impact on power consumption
-     */
-     public void setListenState(Channel c, int timeout) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
-     }
-
-    /**
      * Initiates peer discovery
      */
     public void discoverPeers(Channel c) {
@@ -288,22 +264,6 @@
     }
 
     /**
-     * Initiates peer discovery with a timeout
-     */
-    public void discoverPeers(Channel c, int timeout) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
-    }
-
-    /**
-     * Cancel any existing peer discovery operation
-     */
-    public void cancelPeerDiscovery(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
-    }
-
-    /**
      * Start a p2p connection
      *
      * @param peer Configuration described in a {@link WifiP2pConfig} object.
@@ -314,14 +274,6 @@
     }
 
     /**
-     * Cancel any ongoing negotiation or disconnect from an existing group
-     */
-    public void disconnect(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(CANCEL_CONNECT);
-    }
-
-    /**
      * Create a p2p group. This is essentially an access point that can accept
      * client connections.
      */
@@ -340,15 +292,6 @@
     }
 
     /**
-     * Request current p2p settings. This returns a RESPONSE_SETTINGS on the source
-     * handler.
-     */
-    public void requestP2pSettings(Channel c) {
-        if (c == null) return;
-        c.mAsyncChannel.sendMessage(REQUEST_SETTINGS);
-    }
-
-    /**
      * Request the list of peers. This returns a RESPONSE_PEERS on the source
      * handler.
      */
@@ -365,12 +308,19 @@
     }
 
     /**
-     * Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on
+     * Request device connection info. This returns a RESPONSE_CONNECTION_INFO on
      * the source handler.
      */
-    public void requestConnectionStatus(Channel c) {
+    public void requestConnectionInfo(Channel c) {
         if (c == null) return;
-        c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
+        c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_INFO);
+    }
+
+    /**
+     * Fetch p2p connection status from a RESPONSE_CONNECTION_INFO message
+     */
+    public WifiP2pInfo connectionInfoInResponse(Message msg) {
+        return (WifiP2pInfo) msg.obj;
     }
 
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 4447971..adf13be 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -93,12 +93,25 @@
     private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
 
     private P2pStateMachine mP2pStateMachine;
-    private AsyncChannel mReplyChannel = new AsyncChannel();;
+    private AsyncChannel mReplyChannel = new AsyncChannel();
     private AsyncChannel mWifiChannel;
 
-    private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 60 * 1000;
+    /* Two minutes comes from the wpa_supplicant setting */
+    private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 120 * 1000;
     private static int mGroupNegotiationTimeoutIndex = 0;
 
+    /**
+     * Delay between restarts upon failure to setup connection with supplicant
+     */
+    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
+
+    /**
+     * Number of times we attempt to restart p2p
+     */
+    private static final int P2P_RESTART_TRIES = 5;
+
+    private int mP2pRestartCount = 0;
+
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
     /* Message sent to WifiStateMachine to indicate p2p enable is pending */
@@ -115,14 +128,17 @@
     private final boolean mP2pSupported;
 
     private NetworkInfo mNetworkInfo;
-    private LinkProperties mLinkProperties;
+
+    /* Is chosen as a unique range to avoid conflict with
+       the range defined in Tethering.java */
+    private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
+    private static final String SERVER_ADDRESS = "192.168.49.1";
 
     public WifiP2pService(Context context) {
         mContext = context;
 
         mInterface = SystemProperties.get("wifi.interface", "wlan0");
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
-        mLinkProperties = new LinkProperties();
 
         mP2pSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifi_p2p_support);
@@ -205,6 +221,7 @@
         private P2pNotSupportedState mP2pNotSupportedState = new P2pNotSupportedState();
         private P2pDisablingState mP2pDisablingState = new P2pDisablingState();
         private P2pDisabledState mP2pDisabledState = new P2pDisabledState();
+        private WaitForUserActionState mWaitForUserActionState = new WaitForUserActionState();
         private WaitForWifiDisableState mWaitForWifiDisableState = new WaitForWifiDisableState();
         private P2pEnablingState mP2pEnablingState = new P2pEnablingState();
         private P2pEnabledState mP2pEnabledState = new P2pEnabledState();
@@ -216,11 +233,9 @@
         private WifiMonitor mWifiMonitor = new WifiMonitor(this);
 
         private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
+        private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
         private WifiP2pGroup mGroup;
 
-        // Saved enable request message so the state machine can send an appropriate response
-        private Message mSavedEnableRequestMessage;
-
         // Saved WifiP2pConfig from GO negotiation request
         private WifiP2pConfig mSavedGoNegotiationConfig;
 
@@ -237,7 +252,8 @@
                 addState(mP2pNotSupportedState, mDefaultState);
                 addState(mP2pDisablingState, mDefaultState);
                 addState(mP2pDisabledState, mDefaultState);
-                addState(mWaitForWifiDisableState, mDefaultState);
+                    addState(mWaitForUserActionState, mP2pDisabledState);
+                    addState(mWaitForWifiDisableState, mP2pDisabledState);
                 addState(mP2pEnablingState, mDefaultState);
                 addState(mP2pEnabledState, mDefaultState);
                     addState(mInactiveState, mP2pEnabledState);
@@ -251,27 +267,26 @@
             }
         }
 
-    // TODO: Respond to every p2p request with success/failure
     class DefaultState extends State {
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        if (DBG) Slog.d(TAG, "Full connection with WifiStateMachine established");
+                        if (DBG) logd("Full connection with WifiStateMachine established");
                         mWifiChannel = (AsyncChannel) message.obj;
                     } else {
-                        Slog.e(TAG, "Full connection failure, error = " + message.arg1);
+                        loge("Full connection failure, error = " + message.arg1);
                         mWifiChannel = null;
                     }
                     break;
 
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                     if (message.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
-                        Slog.e(TAG, "Send failed, client connection lost");
+                        loge("Send failed, client connection lost");
                     } else {
-                        Slog.e(TAG, "Client connection lost with reason: " + message.arg1);
+                        loge("Client connection lost with reason: " + message.arg1);
                     }
                     mWifiChannel = null;
                     break;
@@ -286,47 +301,35 @@
                     deferMessage(message);
                     break;
                 case WifiP2pManager.ENABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED);
                     break;
                 case WifiP2pManager.DISABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
-                    break;
-                case WifiP2pManager.START_LISTEN_MODE:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED);
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED);
                     break;
                 case WifiP2pManager.DISCOVER_PEERS:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
-                    break;
-                case WifiP2pManager.CANCEL_DISCOVER_PEERS:
-                    mReplyChannel.replyToMessage(message,
-                            WifiP2pManager.CANCEL_DISCOVER_PEERS_FAILED);
+                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
                     break;
                 case WifiP2pManager.CONNECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
-                    break;
-                case WifiP2pManager.CANCEL_CONNECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED);
-                    break;
-                case WifiP2pManager.REJECT:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.REJECT_FAILED);
+                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
                     break;
                 case WifiP2pManager.CREATE_GROUP:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
+                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
                     break;
                 case WifiP2pManager.REMOVE_GROUP:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
                     break;
-                // TODO: fix
-                case WifiP2pManager.REQUEST_SETTINGS:
                 case WifiP2pManager.REQUEST_PEERS:
-                case WifiP2pManager.REQUEST_CONNECTION_STATUS:
+                    replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    break;
+                case WifiP2pManager.REQUEST_CONNECTION_INFO:
+                    replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
                     break;
                 // Ignore
                 case WIFI_DISABLE_USER_ACCEPT:
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     break;
                 default:
-                    Slog.e(TAG, "Unhandled message " + message);
+                    loge("Unhandled message " + message);
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -339,17 +342,33 @@
             switch (message.what) {
                 // Allow Wi-Fi to proceed
                 case WifiStateMachine.WIFI_ENABLE_PENDING:
-                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    replyToMessage(message, WIFI_ENABLE_PROCEED);
                     break;
                 case WifiP2pManager.ENABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_FAILED,
                             WifiP2pManager.P2P_UNSUPPORTED);
                     break;
                 case WifiP2pManager.DISABLE_P2P:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_FAILED,
                             WifiP2pManager.P2P_UNSUPPORTED);
                     break;
-                default:
+                case WifiP2pManager.DISCOVER_PEERS:
+                    replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.CONNECT:
+                    replyToMessage(message, WifiP2pManager.CONNECT_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.CREATE_GROUP:
+                    replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+                case WifiP2pManager.REMOVE_GROUP:
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED,
+                            WifiP2pManager.P2P_UNSUPPORTED);
+                    break;
+               default:
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -359,17 +378,27 @@
     class P2pDisablingState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
-            transitionTo(mP2pDisabledState);
+            if (DBG) logd(getName());
+            logd("stopping supplicant");
+            if (!WifiNative.stopSupplicant()) {
+                loge("Failed to stop supplicant, issue kill");
+                WifiNative.killSupplicant();
+            }
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    logd("Supplicant connection lost");
+                    WifiNative.closeSupplicantConnection();
                     transitionTo(mP2pDisabledState);
                     break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -381,23 +410,22 @@
     class P2pDisabledState extends State {
        @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiP2pManager.ENABLE_P2P:
-                    mSavedEnableRequestMessage = Message.obtain(message);
                     OnClickListener listener = new OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                             if (which == DialogInterface.BUTTON_POSITIVE) {
                                 sendMessage(WIFI_DISABLE_USER_ACCEPT);
                             } else {
-                                mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                                        WifiP2pManager.ENABLE_P2P_FAILED);
+                                logd("User rejected enabling p2p");
+                                //ignore
                             }
                         }
                     };
@@ -414,17 +442,43 @@
                             .create();
                         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
                         dialog.show();
+                        transitionTo(mWaitForUserActionState);
                     } else {
                         mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
                         transitionTo(mWaitForWifiDisableState);
                     }
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
                     break;
+                case WifiP2pManager.DISABLE_P2P:
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
+                    break;
+                case WifiStateMachine.WIFI_ENABLE_PENDING:
+                    replyToMessage(message, WIFI_ENABLE_PROCEED);
+                    break;
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
+    class WaitForUserActionState extends State {
+        @Override
+        public void enter() {
+            if (DBG) logd(getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) logd(getName() + message.toString());
+            switch (message.what) {
                 case WIFI_DISABLE_USER_ACCEPT:
                     mWifiChannel.sendMessage(P2P_ENABLE_PENDING);
                     transitionTo(mWaitForWifiDisableState);
                     break;
-                case WifiStateMachine.WIFI_ENABLE_PENDING:
-                    mReplyChannel.replyToMessage(message, WIFI_ENABLE_PROCEED);
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -436,31 +490,42 @@
     class WaitForWifiDisableState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiStateMachine.P2P_ENABLE_PROCEED:
                     try {
                         mNwService.wifiFirmwareReload(mInterface, "P2P");
                     } catch (Exception e) {
-                        Slog.e(TAG, "Failed to reload p2p firmware " + e);
+                        loge("Failed to reload p2p firmware " + e);
                         // continue
                     }
+
+                    //A runtime crash can leave the interface up and
+                    //this affects p2p when supplicant starts up.
+                    //Ensure interface is down before a supplicant start.
+                    try {
+                        mNwService.setInterfaceDown(mInterface);
+                    } catch (Exception e) {
+                        if (DBG) Slog.w(TAG, "Unable to bring down wlan interface: " + e);
+                    }
+
                     if (WifiNative.startSupplicant()) {
-                        Slog.d(TAG, "Wi-fi Direct start successful");
                         mWifiMonitor.startMonitoring();
                         transitionTo(mP2pEnablingState);
                     } else {
                         notifyP2pEnableFailure();
-                        mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                                WifiP2pManager.ENABLE_P2P_FAILED);
                         transitionTo(mP2pDisabledState);
                     }
                     break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -471,22 +536,32 @@
     class P2pEnablingState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.SUP_CONNECTION_EVENT:
-                    mReplyChannel.replyToMessage(mSavedEnableRequestMessage,
-                            WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+                    logd("P2p start successful");
                     transitionTo(mInactiveState);
                     break;
-                case WifiP2pManager.DISABLE_P2P:
-                    //TODO: fix
-                    WifiNative.killSupplicant();
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:
+                    if (++mP2pRestartCount <= P2P_RESTART_TRIES) {
+                        loge("Failed to start p2p, retry");
+                        WifiNative.killSupplicant();
+                        sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
+                    } else {
+                        loge("Failed " + mP2pRestartCount + " times to start p2p, quit ");
+                        mP2pRestartCount = 0;
+                    }
                     transitionTo(mP2pDisabledState);
+                    break;
+                case WifiP2pManager.ENABLE_P2P:
+                case WifiP2pManager.DISABLE_P2P:
+                    deferMessage(message);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -497,27 +572,32 @@
     class P2pEnabledState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             sendP2pStateChangedBroadcast(true);
             mNetworkInfo.setIsAvailable(true);
+            //Start listening for new connections
+            WifiNative.p2pListen();
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
+                case WifiP2pManager.ENABLE_P2P:
+                    replyToMessage(message, WifiP2pManager.ENABLE_P2P_SUCCEEDED);
+                    break;
                 case WifiP2pManager.DISABLE_P2P:
-                    // TODO: use stopSupplicant after control channel fixed
-                    WifiNative.killSupplicant();
+                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
+                    replyToMessage(message, WifiP2pManager.DISABLE_P2P_SUCCEEDED);
                     transitionTo(mP2pDisablingState);
                     break;
                 case WifiP2pManager.DISCOVER_PEERS:
                     int timeout = message.arg1;
-                    WifiNative.p2pFlush();
-                    WifiNative.p2pFind(timeout);
-                   break;
-                case WifiP2pManager.REQUEST_PEERS:
-                    mReplyChannel.replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+                    if (WifiNative.p2pFind(timeout)) {
+                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED);
+                    }
                     break;
                 case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
                     WifiP2pDevice device = (WifiP2pDevice) message.obj;
@@ -529,23 +609,34 @@
                     if (mPeers.remove(device)) sendP2pPeersChangedBroadcast();
                     break;
                 case WifiP2pManager.CONNECT:
-                    if (DBG) Slog.d(TAG, getName() + " sending connect");
+                    if (DBG) logd(getName() + " sending connect");
                     mSavedConnectConfig = (WifiP2pConfig) message.obj;
-                    String pin = WifiNative.p2pConnect(mSavedConnectConfig);
-                    try {
-                        Integer.parseInt(pin);
-                        notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
-                    } catch (NumberFormatException ignore) {
-                        // do nothing if p2pConnect did not return a pin
+                    int netId = configuredNetworkId(mSavedConnectConfig.deviceAddress);
+                    if (netId >= 0) {
+                        //TODO: if failure, remove config and do a regular p2pConnect()
+                        WifiNative.p2pReinvoke(netId, mSavedConnectConfig.deviceAddress);
+                    } else {
+                        //TODO: Check if device is a GO and "join"
+                        String pin = WifiNative.p2pConnect(mSavedConnectConfig, false);
+                        try {
+                            Integer.parseInt(pin);
+                            notifyWpsPin(pin, mSavedConnectConfig.deviceAddress);
+                        } catch (NumberFormatException ignore) {
+                            // do nothing if p2pConnect did not return a pin
+                        }
                     }
                     updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.INVITED);
                     sendP2pPeersChangedBroadcast();
+                    replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
                     transitionTo(mGroupNegotiationState);
                     break;
-                case WifiP2pManager.REJECT:
-                    if (DBG) Slog.d(TAG, getName() + " sending reject");
-                    WifiNative.p2pReject((String) message.obj);
-                    break;
+                case WifiMonitor.SUP_DISCONNECTION_EVENT:  /* Supplicant died */
+                    loge("Connection lost, restart p2p");
+                    WifiNative.killSupplicant();
+                    WifiNative.closeSupplicantConnection();
+                    if (mPeers.clear()) sendP2pPeersChangedBroadcast();
+                    transitionTo(mP2pDisabledState);
+                    sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
                 default:
                     return NOT_HANDLED;
             }
@@ -561,28 +652,30 @@
 
     class InactiveState extends State {
         @Override public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT:
                     mSavedGoNegotiationConfig = (WifiP2pConfig) message.obj;
                     notifyP2pGoNegotationRequest(mSavedGoNegotiationConfig);
                     break;
                 case WifiP2pManager.CREATE_GROUP:
-                    WifiNative.p2pGroupAdd();
+                    if (WifiNative.p2pGroupAdd()) {
+                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED);
+                    }
                     transitionTo(mGroupNegotiationState);
                     break;
                 case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT:
                     WifiP2pGroup group = (WifiP2pGroup) message.obj;
                     notifyP2pInvitationReceived(group);
                     break;
-                case WifiP2pManager.REQUEST_PEERS:
-                    return NOT_HANDLED;
-               default:
+                default:
                     return NOT_HANDLED;
             }
             return HANDLED;
@@ -592,31 +685,32 @@
     class GroupNegotiationState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             sendMessageDelayed(obtainMessage(GROUP_NEGOTIATION_TIMED_OUT,
                     ++mGroupNegotiationTimeoutIndex, 0), GROUP_NEGOTIATION_WAIT_TIME_MS);
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 // We ignore these right now, since we get a GROUP_STARTED notification
                 // afterwards
                 case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
                 case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:
-                    if (DBG) Slog.d(TAG, getName() + " go success");
+                    if (DBG) logd(getName() + " go success");
                     break;
                 case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
                 case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
-                    if (DBG) Slog.d(TAG, getName() + " go failure");
+                    if (DBG) logd(getName() + " go failure");
                     updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
                     mSavedConnectConfig = null;
+                    sendP2pPeersChangedBroadcast();
                     transitionTo(mInactiveState);
                     break;
                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:
                     mGroup = (WifiP2pGroup) message.obj;
-                    if (DBG) Slog.d(TAG, getName() + " group started");
+                    if (DBG) logd(getName() + " group started");
                     if (mGroup.isGroupOwner()) {
                         startDhcpServer(mGroup.getInterface());
                     } else {
@@ -629,14 +723,12 @@
                     }
                     transitionTo(mGroupCreatedState);
                     break;
-                case WifiP2pManager.CANCEL_CONNECT:
-                    // TODO: fix
-                    break;
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     if (mGroupNegotiationTimeoutIndex == message.arg1) {
-                        if (DBG) Slog.d(TAG, "Group negotiation timed out");
+                        if (DBG) logd("Group negotiation timed out");
                         updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
                         mSavedConnectConfig = null;
+                        sendP2pPeersChangedBroadcast();
                         transitionTo(mInactiveState);
                     }
                     break;
@@ -650,17 +742,19 @@
     class GroupCreatedState extends State {
         @Override
         public void enter() {
-            if (DBG) Slog.d(TAG, getName());
+            if (DBG) logd(getName());
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
 
+            //DHCP server has already been started if I am a group owner
             if (mGroup.isGroupOwner()) {
+                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
                 sendP2pConnectionChangedBroadcast();
             }
         }
 
         @Override
         public boolean processMessage(Message message) {
-            if (DBG) Slog.d(TAG, getName() + message.toString());
+            if (DBG) logd(getName() + message.toString());
             switch (message.what) {
                 case WifiMonitor.AP_STA_CONNECTED_EVENT:
                     //After a GO setup, STA connected event comes with interface address
@@ -668,7 +762,7 @@
                     String deviceAddress = getDeviceAddress(interfaceAddress);
                     mGroup.addClient(deviceAddress);
                     updateDeviceStatus(deviceAddress, Status.CONNECTED);
-                    if (DBG) Slog.d(TAG, getName() + " ap sta connected");
+                    if (DBG) logd(getName() + " ap sta connected");
                     sendP2pPeersChangedBroadcast();
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
@@ -676,40 +770,37 @@
                     deviceAddress = getDeviceAddress(interfaceAddress);
                     updateDeviceStatus(deviceAddress, Status.AVAILABLE);
                     if (mGroup.removeClient(deviceAddress)) {
-                        if (DBG) Slog.d(TAG, "Removed client " + deviceAddress);
-                        if (mGroup.isClientListEmpty()) {
-                            Slog.d(TAG, "Client list empty, killing p2p connection");
-                            sendMessage(WifiP2pManager.REMOVE_GROUP);
-                        } else {
-                            // Just send a notification
-                            sendP2pPeersChangedBroadcast();
-                        }
+                        if (DBG) logd("Removed client " + deviceAddress);
+                        sendP2pPeersChangedBroadcast();
                     } else {
-                        if (DBG) Slog.d(TAG, "Failed to remove client " + deviceAddress);
+                        if (DBG) logd("Failed to remove client " + deviceAddress);
                         for (WifiP2pDevice c : mGroup.getClientList()) {
-                            if (DBG) Slog.d(TAG,"client " + c.deviceAddress);
+                            if (DBG) logd("client " + c.deviceAddress);
                         }
                     }
-                    if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
+                    if (DBG) loge(getName() + " ap sta disconnected");
                     break;
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                     DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
-                    if (DBG) Slog.d(TAG, "DhcpInfo: " + dhcpInfo);
-                    if (dhcpInfo != null) {
-                        mLinkProperties = dhcpInfo.makeLinkProperties();
-                        mLinkProperties.setInterfaceName(mGroup.getInterface());
+                    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
+                            dhcpInfo != null) {
+                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
+                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
                         sendP2pConnectionChangedBroadcast();
+                    } else {
+                        WifiNative.p2pGroupRemove(mGroup.getInterface());
                     }
                     break;
-                //disconnect & remove group have same effect when connected
-                case WifiP2pManager.CANCEL_CONNECT:
                 case WifiP2pManager.REMOVE_GROUP:
-                    if (DBG) Slog.e(TAG, getName() + " remove group");
-                    WifiNative.p2pFlush();
-                    WifiNative.p2pGroupRemove(mGroup.getInterface());
+                    if (DBG) loge(getName() + " remove group");
+                    if (WifiNative.p2pGroupRemove(mGroup.getInterface())) {
+                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED);
+                    }
                     break;
                 case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
-                    if (DBG) Slog.e(TAG, getName() + " group removed");
+                    if (DBG) loge(getName() + " group removed");
                     Collection <WifiP2pDevice> devices = mGroup.getClientList();
                     boolean changed = false;
                     for (WifiP2pDevice d : mPeers.getDeviceList()) {
@@ -722,7 +813,7 @@
                     if (mGroup.isGroupOwner()) {
                         stopDhcpServer();
                     } else {
-                        if (DBG) Slog.d(TAG, "stop DHCP client");
+                        if (DBG) logd("stop DHCP client");
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
                         mDhcpStateMachine.quit();
                         mDhcpStateMachine = null;
@@ -735,33 +826,30 @@
                 case WifiMonitor.P2P_DEVICE_LOST_EVENT:
                     WifiP2pDevice device = (WifiP2pDevice) message.obj;
                     if (device.equals(mGroup.getOwner())) {
-                        Slog.d(TAG, "Lost the group owner, killing p2p connection");
-                        WifiNative.p2pFlush();
+                        logd("Lost the group owner, killing p2p connection");
                         WifiNative.p2pGroupRemove(mGroup.getInterface());
-                    } else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
-                        Slog.d(TAG, "Client list empty, killing p2p connection");
-                        WifiNative.p2pFlush();
-                        WifiNative.p2pGroupRemove(mGroup.getInterface());
+                    } else {
+                        mGroup.removeClient(device);
                     }
                     return NOT_HANDLED; // Do the regular device lost handling
                 case WifiP2pManager.DISABLE_P2P:
                     sendMessage(WifiP2pManager.REMOVE_GROUP);
                     deferMessage(message);
                     break;
-                case WifiP2pManager.DISCOVER_PEERS:
-                    int timeout = message.arg1;
-                    WifiNative.p2pFind(timeout);
-                    break;
                 case WifiP2pManager.CONNECT:
                     WifiP2pConfig config = (WifiP2pConfig) message.obj;
-                    Slog.d(TAG, "Inviting device : " + config.deviceAddress);
-                    WifiNative.p2pInvite(mGroup, config.deviceAddress);
-                    updateDeviceStatus(config.deviceAddress, Status.INVITED);
-                    sendP2pPeersChangedBroadcast();
+                    logd("Inviting device : " + config.deviceAddress);
+                    if (WifiNative.p2pInvite(mGroup, config.deviceAddress)) {
+                        updateDeviceStatus(config.deviceAddress, Status.INVITED);
+                        sendP2pPeersChangedBroadcast();
+                        replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
+                    } else {
+                        replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
+                    }
                     // TODO: figure out updating the status to declined when invitation is rejected
                     break;
                 case WifiMonitor.P2P_INVITATION_RESULT_EVENT:
-                    Slog.d(TAG,"===> INVITATION RESULT EVENT : " + message.obj);
+                    logd("===> INVITATION RESULT EVENT : " + message.obj);
                     break;
                 case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT:
                     notifyP2pProvDiscPbcRequest((WifiP2pDevice) message.obj);
@@ -782,7 +870,9 @@
         }
 
         public void exit() {
+            setWifiP2pInfoOnGroupTermination();
             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+            sendP2pConnectionChangedBroadcast();
         }
     }
 
@@ -806,52 +896,42 @@
     }
 
     private void sendP2pConnectionChangedBroadcast() {
-        if (DBG) Slog.d(TAG, "sending p2p connection changed broadcast");
+        if (DBG) logd("sending p2p connection changed broadcast");
         Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
         intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
-        intent.putExtra(WifiP2pManager.EXTRA_LINK_PROPERTIES,
-                new LinkProperties (mLinkProperties));
         mContext.sendStickyBroadcast(intent);
     }
 
     private void startDhcpServer(String intf) {
-        /* Is chosen as a unique range to avoid conflict with
-           the range defined in Tethering.java */
-        String[] dhcp_range = {"192.168.49.2", "192.168.49.254"};
-        String serverAddress = "192.168.49.1";
-
-        mLinkProperties.clear();
-        mLinkProperties.setInterfaceName(mGroup.getInterface());
-
         InterfaceConfiguration ifcg = null;
         try {
             ifcg = mNwService.getInterfaceConfig(intf);
             ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
-                        serverAddress), 24);
+                        SERVER_ADDRESS), 24);
             ifcg.interfaceFlags = "[up]";
             mNwService.setInterfaceConfig(intf, ifcg);
             /* This starts the dnsmasq server */
-            mNwService.startTethering(dhcp_range);
+            mNwService.startTethering(DHCP_RANGE);
         } catch (Exception e) {
-            Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+            loge("Error configuring interface " + intf + ", :" + e);
             return;
         }
 
-        mLinkProperties.addDns(NetworkUtils.numericToInetAddress(serverAddress));
-        Slog.d(TAG, "Started Dhcp server on " + intf);
-    }
+        logd("Started Dhcp server on " + intf);
+   }
 
     private void stopDhcpServer() {
         try {
             mNwService.stopTethering();
         } catch (Exception e) {
-            Slog.e(TAG, "Error stopping Dhcp server" + e);
+            loge("Error stopping Dhcp server" + e);
             return;
         }
 
-        Slog.d(TAG, "Stopped Dhcp server");
+        logd("Stopped Dhcp server");
     }
 
     private void notifyP2pEnableFailure() {
@@ -888,7 +968,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
-                            if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
+                            if (DBG) logd(getName() + " connect " + pin.getText());
 
                             if (pin.getVisibility() == View.GONE) {
                                 mSavedGoNegotiationConfig.wpsConfig.setup = Setup.PBC;
@@ -903,10 +983,8 @@
             .setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
-                                if (DBG) Slog.d(TAG, getName() + " reject");
-                                sendMessage(WifiP2pManager.REJECT,
-                                        mSavedGoNegotiationConfig.deviceAddress);
-                                mSavedGoNegotiationConfig = null;
+                            if (DBG) logd(getName() + " ignore connect");
+                            mSavedGoNegotiationConfig = null;
                         }
                     })
             .create();
@@ -935,7 +1013,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                         public void onClick(DialogInterface dialog, int which) {
-                                if (DBG) Slog.d(TAG, getName() + " wps_pbc");
+                                if (DBG) logd(getName() + " wps_pbc");
                                 sendMessage(WifiP2pManager.WPS_PBC);
                         }
                     })
@@ -961,7 +1039,7 @@
             .setView(textEntryView)
             .setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
                     public void onClick(DialogInterface dialog, int which) {
-                        if (DBG) Slog.d(TAG, getName() + " wps_pin");
+                        if (DBG) logd(getName() + " wps_pin");
                         sendMessage(WifiP2pManager.WPS_PIN, pin.getText().toString());
                     }
                     })
@@ -989,8 +1067,7 @@
                         public void onClick(DialogInterface dialog, int which) {
                                 WifiP2pConfig config = new WifiP2pConfig();
                                 config.deviceAddress = mSavedP2pGroup.getOwner().deviceAddress;
-                                config.joinExistingGroup = true;
-                                if (DBG) Slog.d(TAG, getName() + " connect to invited group");
+                                if (DBG) logd(getName() + " connect to invited group");
                                 sendMessage(WifiP2pManager.CONNECT, config);
                                 mSavedP2pGroup = null;
                         }
@@ -1014,6 +1091,23 @@
         }
     }
 
+    //TODO: implement when wpa_supplicant is fixed
+    private int configuredNetworkId(String deviceAddress) {
+        return -1;
+    }
+
+    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
+        mWifiP2pInfo.groupFormed = true;
+        mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
+        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
+    }
+
+    private void setWifiP2pInfoOnGroupTermination() {
+        mWifiP2pInfo.groupFormed = false;
+        mWifiP2pInfo.isGroupOwner = false;
+        mWifiP2pInfo.groupOwnerAddress = null;
+    }
+
     private String getDeviceAddress(String interfaceAddress) {
         for (WifiP2pDevice d : mPeers.getDeviceList()) {
             if (interfaceAddress.equals(WifiNative.p2pGetInterfaceAddress(d.deviceAddress))) {
@@ -1023,5 +1117,25 @@
         return null;
     }
 
+    //State machine initiated requests can have replyTo set to null indicating
+    //there are no recepients, we ignore those reply actions
+    private void replyToMessage(Message msg, int what) {
+        if (msg.replyTo == null) return;
+        mReplyChannel.replyToMessage(msg, what);
+    }
+
+    private void replyToMessage(Message msg, int what, Object obj) {
+        if (msg.replyTo == null) return;
+        mReplyChannel.replyToMessage(msg, what, obj);
+    }
+
+    private void logd(String s) {
+        Slog.d(TAG, s);
+    }
+
+    private void loge(String s) {
+        Slog.e(TAG, s);
+    }
+
     }
 }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java b/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
deleted file mode 100644
index 1c9b76c..0000000
--- a/wifi/java/android/net/wifi/p2p/WifiP2pStatus.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.p2p;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * A class representing Wi-fi P2p status
- * @hide
- */
-public class WifiP2pStatus implements Parcelable {
-
-    //Comes from the wpa_supplicant
-    enum p2p_status_code {
-        SUCCESS,
-        FAIL_INFO_CURRENTLY_UNAVAILABLE,
-        FAIL_INCOMPATIBLE_PARAMS,
-        FAIL_LIMIT_REACHED,
-        FAIL_INVALID_PARAMS,
-        FAIL_UNABLE_TO_ACCOMMODATE,
-        FAIL_PREV_PROTOCOL_ERROR,
-        FAIL_NO_COMMON_CHANNELS,
-        FAIL_UNKNOWN_GROUP,
-        FAIL_BOTH_GO_INTENT_15,
-        FAIL_INCOMPATIBLE_PROV_METHOD,
-        FAIL_REJECTED_BY_USER
-    };
-
-    public WifiP2pStatus() {
-    }
-
-    //TODO: add support
-    public String toString() {
-        StringBuffer sbuf = new StringBuffer();
-        return sbuf.toString();
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** copy constructor {@hide} */
-    //TODO: implement
-    public WifiP2pStatus(WifiP2pStatus source) {
-        if (source != null) {
-       }
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    // STOPSHIP: implement
-    public void writeToParcel(Parcel dest, int flags) {
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<WifiP2pStatus> CREATOR =
-        new Creator<WifiP2pStatus>() {
-            public WifiP2pStatus createFromParcel(Parcel in) {
-                WifiP2pStatus status = new WifiP2pStatus();
-                return status;
-            }
-
-            public WifiP2pStatus[] newArray(int size) {
-                return new WifiP2pStatus[size];
-            }
-        };
-}