Merge "Change DimAnimator to reflect rotations." into jb-dev
diff --git a/api/current.txt b/api/current.txt
index 133a280..848d563 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -144,6 +144,7 @@
     field public static final java.lang.String AFFECTS_BATTERY = "android.permission-group.AFFECTS_BATTERY";
     field public static final java.lang.String APP_INFO = "android.permission-group.APP_INFO";
     field public static final java.lang.String AUDIO_SETTINGS = "android.permission-group.AUDIO_SETTINGS";
+    field public static final java.lang.String BLUETOOTH_NETWORK = "android.permission-group.BLUETOOTH_NETWORK";
     field public static final java.lang.String BOOKMARKS = "android.permission-group.BOOKMARKS";
     field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
     field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
@@ -169,6 +170,7 @@
     field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
     field public static final java.lang.String VOICEMAIL = "android.permission-group.VOICEMAIL";
     field public static final java.lang.String WALLPAPER = "android.permission-group.WALLPAPER";
+    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission-group.WRITE_USER_DICTIONARY";
   }
 
   public final class R {
@@ -24592,7 +24594,6 @@
     method public android.view.View getFocusedChild();
     method public android.view.animation.LayoutAnimationController getLayoutAnimation();
     method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
-    method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
     method public int getPersistentDrawingCache();
     method public int indexOfChild(android.view.View);
@@ -24640,7 +24641,6 @@
     method public void setDescendantFocusability(int);
     method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
     method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
-    method public void setLayoutMode(int);
     method public void setLayoutTransition(android.animation.LayoutTransition);
     method public void setMotionEventSplittingEnabled(boolean);
     method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
@@ -24652,12 +24652,10 @@
     method public void startLayoutAnimation();
     method public void startViewTransition(android.view.View);
     method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
-    field public static final int CLIP_BOUNDS = 0; // 0x0
     field protected static final int CLIP_TO_PADDING_MASK = 34; // 0x22
     field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
     field public static final int FOCUS_BEFORE_DESCENDANTS = 131072; // 0x20000
     field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
-    field public static final int OPTICAL_BOUNDS = 1; // 0x1
     field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
     field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
     field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2951476..0d76877 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -806,6 +806,10 @@
             contentView.setViewVisibility(R.id.time, View.VISIBLE);
             contentView.setLong(R.id.time, "setTime", when);
         }
+        if (this.number != 0) {
+            NumberFormat f = NumberFormat.getIntegerInstance();
+            contentView.setTextViewText(R.id.info, f.format(this.number));
+        }
 
         this.contentView = contentView;
         this.contentIntent = contentIntent;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 98b40eb..ad52e13 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1458,7 +1458,7 @@
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
         perm.info.priority = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
-        if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) != 0) {
+        if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
             perm.info.priority = 0;
         }
 
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 4aa7fe2..0abc149 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -97,8 +97,8 @@
     private static Message sPool;
     private static int sPoolSize = 0;
 
-    private static final int MAX_POOL_SIZE = 10;
-    
+    private static final int MAX_POOL_SIZE = 50;
+
     /**
      * Return a new Message instance from the global pool. Allows us to
      * avoid allocating new objects in many cases.
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 6d14dfc..7824724 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Callable;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.DataUsageFeedback;
 import android.text.TextUtils;
@@ -312,10 +313,12 @@
                             null);
                 } else {
                     final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
-                    cursor = resolver.query(Phone.CONTENT_URI,
+                    cursor = resolver.query(
+                            Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
+                                    Uri.encode(phoneNumber)),
                             new String[] { Phone._ID },
-                            Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
-                            new String[] { String.valueOf(ci.person_id), phoneNumber},
+                            Phone.CONTACT_ID + " =?",
+                            new String[] { String.valueOf(ci.person_id) },
                             null);
                 }
 
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index c579e6e..77b22ed 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -397,14 +397,6 @@
                 }
                 wordStart = wordIterator.getBeginning(wordEnd);
             }
-            if (originalText.length() >= SpellChecker.WORD_ITERATOR_INTERVAL
-                    && wordItems.size() >= 2) {
-                if (DBG) {
-                    Log.w(TAG, "Remove possibly divided word: "
-                            + wordItems.get(0).mTextInfo.getText());
-                }
-                wordItems.remove(0);
-            }
             return new SentenceTextInfoParams(originalTextInfo, wordItems);
         }
 
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 09c9438..0f30d25 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -308,6 +308,7 @@
             resizeFor(mText.length + nbNewChars - mGapLength);
         }
 
+        final boolean textIsRemoved = replacementLength == 0;
         // The removal pass needs to be done before the gap is updated in order to broadcast the
         // correct previous positions to the correct intersecting SpanWatchers
         if (replacedLength > 0) { // no need for span fixup on pure insertion
@@ -319,12 +320,15 @@
             while (i < mSpanCount) {
                 if ((mSpanFlags[i] & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
                         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
-                mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
-                mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
+                        mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
+                        mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength &&
+                        // This condition indicates that the span would become empty
+                        (textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
                     removeSpan(i);
-                } else {
-                    i++;
+                    continue; // do not increment i, spans will be shifted left in the array
                 }
+
+                i++;
             }
         }
 
@@ -338,7 +342,6 @@
 
         if (replacedLength > 0) { // no need for span fixup on pure insertion
             final boolean atEnd = (mGapStart + mGapLength == mText.length);
-            final boolean textIsRemoved = replacementLength == 0;
 
             for (int i = 0; i < mSpanCount; i++) {
                 final int startFlag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
@@ -390,9 +393,9 @@
                         return mGapStart + mGapLength;
                     }
                 } else { // MARK
-                    // MARKs should be moved to the start, with the exception of a mark located at the
-                    // end of the range (which will be < mGapStart + mGapLength since mGapLength > 0)
-                    // which should stay 'unchanged' at the end of the replaced text.
+                    // MARKs should be moved to the start, with the exception of a mark located at
+                    // the end of the range (which will be < mGapStart + mGapLength since mGapLength
+                    // is > 0, which should stay 'unchanged' at the end of the replaced text.
                     if (textIsRemoved || offset < mGapStart - nbNewChars) {
                         return start;
                     } else {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c0771c5..e25e2ef 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -152,7 +152,7 @@
     /**
      * Number of frames to profile.
      */
-    private static final int PROFILE_MAX_FRAMES = 64;
+    private static final int PROFILE_MAX_FRAMES = 128;
 
     /**
      * Number of floats per profiled frame.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a5ae248..29613d5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -348,6 +348,8 @@
      * This constant is a {@link #setLayoutMode(int) layoutMode}.
      * Clip bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
      * {@link #getRight() right} and {@link #getBottom() bottom}.
+     *
+     * @hide
      */
     public static final int CLIP_BOUNDS = 0;
 
@@ -356,6 +358,8 @@
      * Optical bounds describe where a widget appears to be. They sit inside the clip
      * bounds which need to cover a larger area to allow other effects,
      * such as shadows and glows, to be drawn.
+     *
+     * @hide
      */
     public static final int OPTICAL_BOUNDS = 1;
 
@@ -4539,6 +4543,8 @@
      * @return the layout mode to use during layout operations
      *
      * @see #setLayoutMode(int)
+     *
+     * @hide
      */
     public int getLayoutMode() {
         return mLayoutMode;
@@ -4553,6 +4559,8 @@
      * @param layoutMode the layout mode to use during layout operations
      *
      * @see #getLayoutMode()
+     *
+     * @hide
      */
     public void setLayoutMode(int layoutMode) {
         if (mLayoutMode != layoutMode) {
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index c169de4..fe812af 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -56,6 +56,8 @@
 import java.util.Set;
 
 import org.apache.harmony.security.provider.cert.X509CertImpl;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
 
 class BrowserFrame extends Handler {
 
@@ -1104,12 +1106,23 @@
         SslClientCertLookupTable table = SslClientCertLookupTable.getInstance();
         if (table.IsAllowed(hostAndPort)) {
             // previously allowed
-            nativeSslClientCert(handle,
-                                table.PrivateKey(hostAndPort),
-                                table.CertificateChain(hostAndPort));
+            PrivateKey pkey = table.PrivateKey(hostAndPort);
+            if (pkey instanceof OpenSSLRSAPrivateKey) {
+                nativeSslClientCert(handle,
+                                    ((OpenSSLRSAPrivateKey)pkey).getPkeyContext(),
+                                    table.CertificateChain(hostAndPort));
+            } else if (pkey instanceof OpenSSLDSAPrivateKey) {
+                nativeSslClientCert(handle,
+                                    ((OpenSSLDSAPrivateKey)pkey).getPkeyContext(),
+                                    table.CertificateChain(hostAndPort));
+            } else {
+                nativeSslClientCert(handle,
+                                    pkey.getEncoded(),
+                                    table.CertificateChain(hostAndPort));
+            }
         } else if (table.IsDenied(hostAndPort)) {
             // previously denied
-            nativeSslClientCert(handle, null, null);
+            nativeSslClientCert(handle, 0, null);
         } else {
             // previously ignored or new
             mCallbackProxy.onReceivedClientCertRequest(
@@ -1296,7 +1309,11 @@
     private native void nativeSslCertErrorCancel(int handle, int certError);
 
     native void nativeSslClientCert(int handle,
-                                    byte[] pkcs8EncodedPrivateKey,
+                                    int ctx,
+                                    byte[][] asn1DerEncodedCertificateChain);
+
+    native void nativeSslClientCert(int handle,
+                                    byte[] pkey,
                                     byte[][] asn1DerEncodedCertificateChain);
 
     /**
diff --git a/core/java/android/webkit/ClientCertRequestHandler.java b/core/java/android/webkit/ClientCertRequestHandler.java
index f862613..6570a9b8 100644
--- a/core/java/android/webkit/ClientCertRequestHandler.java
+++ b/core/java/android/webkit/ClientCertRequestHandler.java
@@ -21,6 +21,8 @@
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
 
 /**
  * ClientCertRequestHandler: class responsible for handling client
@@ -50,20 +52,23 @@
      * Proceed with the specified private key and client certificate chain.
      */
     public void proceed(PrivateKey privateKey, X509Certificate[] chain) {
-        final byte[] privateKeyBytes = privateKey.getEncoded();
-        final byte[][] chainBytes;
         try {
-            chainBytes = NativeCrypto.encodeCertificates(chain);
-            mTable.Allow(mHostAndPort, privateKeyBytes, chainBytes);
-            post(new Runnable() {
-                    public void run() {
-                        mBrowserFrame.nativeSslClientCert(mHandle, privateKeyBytes, chainBytes);
-                    }
-                });
+            byte[][] chainBytes = NativeCrypto.encodeCertificates(chain);
+            mTable.Allow(mHostAndPort, privateKey, chainBytes);
+
+            if (privateKey instanceof OpenSSLRSAPrivateKey) {
+                setSslClientCertFromCtx(((OpenSSLRSAPrivateKey)privateKey).getPkeyContext(),
+                           chainBytes);
+            } else if (privateKey instanceof OpenSSLDSAPrivateKey) {
+                setSslClientCertFromCtx(((OpenSSLDSAPrivateKey)privateKey).getPkeyContext(),
+                           chainBytes);
+            } else {
+                setSslClientCertFromPKCS8(privateKey.getEncoded(),chainBytes);
+            }
         } catch (CertificateEncodingException e) {
             post(new Runnable() {
                     public void run() {
-                        mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+                        mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
                         return;
                     }
                 });
@@ -71,12 +76,34 @@
     }
 
     /**
+     * Proceed with the specified private key bytes and client certificate chain.
+     */
+    private void setSslClientCertFromCtx(final int ctx, final byte[][] chainBytes) {
+        post(new Runnable() {
+                public void run() {
+                    mBrowserFrame.nativeSslClientCert(mHandle, ctx, chainBytes);
+                }
+            });
+    }
+
+    /**
+     * Proceed with the specified private key context and client certificate chain.
+     */
+    private void setSslClientCertFromPKCS8(final byte[] key, final byte[][] chainBytes) {
+        post(new Runnable() {
+                public void run() {
+                    mBrowserFrame.nativeSslClientCert(mHandle, key, chainBytes);
+                }
+            });
+    }
+
+    /**
      * Igore the request for now, the user may be prompted again.
      */
     public void ignore() {
         post(new Runnable() {
                 public void run() {
-                    mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+                    mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
                 }
             });
     }
@@ -88,7 +115,7 @@
         mTable.Deny(mHostAndPort);
         post(new Runnable() {
                 public void run() {
-                    mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+                    mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
                 }
             });
     }
diff --git a/core/java/android/webkit/SslClientCertLookupTable.java b/core/java/android/webkit/SslClientCertLookupTable.java
index 630debd..c52b7e8 100644
--- a/core/java/android/webkit/SslClientCertLookupTable.java
+++ b/core/java/android/webkit/SslClientCertLookupTable.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import java.security.PrivateKey;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -26,7 +27,7 @@
  */
 final class SslClientCertLookupTable {
     private static SslClientCertLookupTable sTable;
-    private final Map<String, byte[]> privateKeys;
+    private final Map<String, PrivateKey> privateKeys;
     private final Map<String, byte[][]> certificateChains;
     private final Set<String> denied;
 
@@ -38,12 +39,12 @@
     }
 
     private SslClientCertLookupTable() {
-        privateKeys = new HashMap<String, byte[]>();
+        privateKeys = new HashMap<String, PrivateKey>();
         certificateChains = new HashMap<String, byte[][]>();
         denied = new HashSet<String>();
     }
 
-    public void Allow(String host_and_port, byte[] privateKey, byte[][] chain) {
+    public void Allow(String host_and_port, PrivateKey privateKey, byte[][] chain) {
         privateKeys.put(host_and_port, privateKey);
         certificateChains.put(host_and_port, chain);
         denied.remove(host_and_port);
@@ -63,7 +64,7 @@
         return denied.contains(host_and_port);
     }
 
-    public byte[] PrivateKey(String host_and_port) {
+    public PrivateKey PrivateKey(String host_and_port) {
         return privateKeys.get(host_and_port);
     }
 
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index dcc99d8..eb5f835 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -5753,6 +5753,7 @@
 
         if (mInputDispatcher.postPointerEvent(ev, getScrollX(),
                 getScrollY() - getTitleHeight(), mZoomManager.getInvScale())) {
+            mInputDispatcher.dispatchUiEvents();
             return true;
         } else {
             Log.w(LOGTAG, "mInputDispatcher rejected the event!");
@@ -6021,10 +6022,8 @@
                     }
                     if (deltaX * deltaX + deltaY * deltaY > mTouchSlopSquare) {
                         mHeldMotionless = MOTIONLESS_FALSE;
-                        nativeSetIsScrolling(true);
                     } else {
                         mHeldMotionless = MOTIONLESS_TRUE;
-                        nativeSetIsScrolling(false);
                         keepScrollBarsVisible = true;
                     }
 
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index c53b5f6..fba8d3a 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -761,6 +761,16 @@
     }
 
     /**
+     * Gets whether the given observer is already registered.
+     *
+     * @param observer The observer.
+     * @return True if already registered.
+     */
+    public boolean isRegisteredObserver(DataSetObserver observer) {
+        return mObservers.contains(observer);
+    }
+
+    /**
      * Represents a record in the history.
      */
     public final static class HistoricalRecord {
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index be6b4e2..0c0bb1e 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -20,8 +20,10 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -174,6 +176,11 @@
     private int mDefaultActionButtonContentDescription;
 
     /**
+     * Whether this view has a default activity affordance.
+     */
+    private boolean mHasDefaultActivity;
+
+    /**
      * Create a new instance.
      *
      * @param context The application environment.
@@ -245,6 +252,8 @@
         Resources resources = context.getResources();
         mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
               resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
+
+        updateHasDefaultActivity();
     }
 
     /**
@@ -258,6 +267,21 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        Configuration oldConfig = mContext.getResources().getConfiguration();
+        final int changed = oldConfig.diff(newConfig);
+        if ((changed & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
+                || (changed & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+            updateHasDefaultActivity();
+        }
+    }
+
+    private void updateHasDefaultActivity() {
+        mHasDefaultActivity = mContext.getResources().getBoolean(
+                R.bool.activity_chooser_view_has_default_activity);
+    }
+
     /**
      * Sets the background for the button that expands the activity
      * overflow list.
@@ -383,7 +407,8 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
-        if (dataModel != null) {
+        if (dataModel != null
+                && !dataModel.isRegisteredObserver(mModelDataSetOberver)) {
             dataModel.registerObserver(mModelDataSetOberver);
         }
         mIsAttachedToWindow = true;
@@ -393,7 +418,8 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         ActivityChooserModel dataModel = mAdapter.getDataModel();
-        if (dataModel != null) {
+        if (dataModel != null
+                && dataModel.isRegisteredObserver(mModelDataSetOberver)) {
             dataModel.unregisterObserver(mModelDataSetOberver);
         }
         ViewTreeObserver viewTreeObserver = getViewTreeObserver();
@@ -496,7 +522,7 @@
         // Default activity button.
         final int activityCount = mAdapter.getActivityCount();
         final int historySize = mAdapter.getHistorySize();
-        if (activityCount > 0 && historySize > 0) {
+        if (mHasDefaultActivity && activityCount > 0 && historySize > 0) {
             mDefaultActivityButton.setVisibility(VISIBLE);
             ResolveInfo activity = mAdapter.getDefaultActivity();
             PackageManager packageManager = mContext.getPackageManager();
@@ -512,9 +538,9 @@
         }
         // Activity chooser content.
         if (mDefaultActivityButton.getVisibility() == VISIBLE) {
-            mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
+            mActivityChooserContent.setBackground(mActivityChooserContentBackground);
         } else {
-            mActivityChooserContent.setBackgroundDrawable(null);
+            mActivityChooserContent.setBackground(null);
         }
     }
 
@@ -577,7 +603,7 @@
         // OnLongClickListener#onLongClick
         @Override
         public boolean onLongClick(View view) {
-            if (view == mDefaultActivityButton) {
+            if (mHasDefaultActivity && view == mDefaultActivityButton) {
                 if (mAdapter.getCount() > 0) {
                     mIsSelectingDefaultActivity = true;
                     showPopupUnchecked(mInitialActivityCount);
@@ -630,14 +656,16 @@
 
         public void setDataModel(ActivityChooserModel dataModel) {
             ActivityChooserModel oldDataModel = mAdapter.getDataModel();
-            if (oldDataModel != null && isShown()) {
+            if (oldDataModel != null) {
                 oldDataModel.unregisterObserver(mModelDataSetOberver);
             }
             mDataModel = dataModel;
-            if (dataModel != null && isShown()) {
+            if (dataModel != null) {
                 dataModel.registerObserver(mModelDataSetOberver);
+                notifyDataSetChanged();
+            } else {
+                notifyDataSetInvalidated();
             }
-            notifyDataSetChanged();
         }
 
         @Override
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 5d8bdbb..64f6c07 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -98,6 +98,20 @@
         MyPermissionGroupInfo(PermissionGroupInfo info) {
             super(info);
         }
+
+        public Drawable loadGroupIcon(PackageManager pm) {
+            if (icon != 0) {
+                return loadIcon(pm);
+            } else {
+                ApplicationInfo appInfo;
+                try {
+                    appInfo = pm.getApplicationInfo(packageName, 0);
+                    return appInfo.loadIcon(pm);
+                } catch (NameNotFoundException e) {
+                }
+            }
+            return null;
+        }
     }
 
     static class MyPermissionInfo extends PermissionInfo {
@@ -155,16 +169,7 @@
             PackageManager pm = getContext().getPackageManager();
             Drawable icon = null;
             if (first) {
-                if (grp.icon != 0) {
-                    icon = grp.loadIcon(pm);
-                } else {
-                    ApplicationInfo appInfo;
-                    try {
-                        appInfo = pm.getApplicationInfo(grp.packageName, 0);
-                        icon = appInfo.loadIcon(pm);
-                    } catch (NameNotFoundException e) {
-                    }
-                }
+                icon = grp.loadGroupIcon(pm);
             }
             CharSequence label = perm.mLabel;
             if (perm.mNew && newPermPrefix != null) {
@@ -191,10 +196,28 @@
                 if (mDialog != null) {
                     mDialog.dismiss();
                 }
+                PackageManager pm = getContext().getPackageManager();
                 AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                 builder.setTitle(mGroup.mLabel);
-                builder.setMessage(mPerm.loadDescription(getContext().getPackageManager()));
+                if (mPerm.descriptionRes != 0) {
+                    builder.setMessage(mPerm.loadDescription(pm));
+                } else {
+                    CharSequence appName;
+                    try {
+                        ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
+                        appName = app.loadLabel(pm);
+                    } catch (NameNotFoundException e) {
+                        appName = mPerm.packageName;
+                    }
+                    StringBuilder sbuilder = new StringBuilder(128);
+                    sbuilder.append(getContext().getString(
+                            R.string.perms_description_app, appName));
+                    sbuilder.append("\n\n");
+                    sbuilder.append(mPerm.name);
+                    builder.setMessage(sbuilder.toString());
+                }
                 builder.setCancelable(true);
+                builder.setIcon(mGroup.loadGroupIcon(pm));
                 mDialog = builder.show();
                 mDialog.setCanceledOnTouchOutside(true);
             }
@@ -611,9 +634,26 @@
         }
 
         for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
-            pgrp.mLabel = pgrp.loadLabel(mPm);
+            if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
+                pgrp.mLabel = pgrp.loadLabel(mPm);
+            } else {
+                ApplicationInfo app;
+                try {
+                    app = mPm.getApplicationInfo(pgrp.packageName, 0);
+                    pgrp.mLabel = app.loadLabel(mPm);
+                } catch (NameNotFoundException e) {
+                    pgrp.mLabel = pgrp.loadLabel(mPm);
+                }
+            }
             mPermGroupsList.add(pgrp);
         }
         Collections.sort(mPermGroupsList, mPermGroupComparator);
+        if (false) {
+            for (MyPermissionGroupInfo grp : mPermGroupsList) {
+                Log.i("foo", "Group " + grp.name + " personal="
+                        + ((grp.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0)
+                        + " priority=" + grp.priority);
+            }
+        }
     }
 }
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 561326e..521597b 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -576,6 +576,8 @@
     /**
      * Returns the default iconified state of the search field.
      * @return
+     *
+     * @attr ref android.R.styleable#SearchView_iconifiedByDefault
      */
     public boolean isIconfiedByDefault() {
         return mIconifiedByDefault;
@@ -696,6 +698,8 @@
      * Gets the specified maximum width in pixels, if set. Returns zero if
      * no maximum width was specified.
      * @return the maximum width of the view
+     *
+     * @attr ref android.R.styleable#SearchView_maxWidth
      */
     public int getMaxWidth() {
         return mMaxWidth;
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 080b87d..367561e 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -44,6 +44,7 @@
  * <code>
  *  // In Activity#onCreateOptionsMenu
  *  public boolean onCreateOptionsMenu(Menu menu) {
+ *      getManuInflater().inflate(R.menu.my_menu, menu);
  *      // Get the menu item.
  *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
  *      // Get the provider and hold onto it to set/change the share intent.
@@ -239,7 +240,11 @@
      * <p>
      * <strong>Note:</strong> The history file name can be set any time, however
      * only the action views created by {@link #onCreateActionView()} after setting
-     * the file name will be backed by the provided file.
+     * the file name will be backed by the provided file. Hence, if you are using
+     * a share action provider on a menu item and want to change the history file
+     * based on the type of the currently selected item, you need to call
+     * {@link android.app.Activity#invalidateOptionsMenu()} to force the system
+     * to recreate the menu UI.
      * <p>
      *
      * @param shareHistoryFile The share history file name.
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 98e45fb..e1103dd 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -21,10 +21,12 @@
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.text.TextUtils;
 import android.text.method.WordIterator;
 import android.text.style.SpellCheckSpan;
 import android.text.style.SuggestionSpan;
 import android.util.Log;
+import android.util.LruCache;
 import android.view.textservice.SentenceSuggestionsInfo;
 import android.view.textservice.SpellCheckerSession;
 import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
@@ -95,6 +97,10 @@
 
     private Runnable mSpellRunnable;
 
+    private static final int SUGGESTION_SPAN_CACHE_SIZE = 10;
+    private final LruCache<Long, SuggestionSpan> mSuggestionSpanCache =
+            new LruCache<Long, SuggestionSpan>(SUGGESTION_SPAN_CACHE_SIZE);
+
     public SpellChecker(TextView textView) {
         mTextView = textView;
 
@@ -126,6 +132,7 @@
 
         // Restore SpellCheckSpans in pool
         for (int i = 0; i < mLength; i++) {
+            // Resets id and progress to invalidate spell check span
             mSpellCheckSpans[i].setSpellCheckInProgress(false);
             mIds[i] = -1;
         }
@@ -133,6 +140,7 @@
 
         // Remove existing misspelled SuggestionSpans
         mTextView.removeMisspelledSpans((Editable) mTextView.getText());
+        mSuggestionSpanCache.evictAll();
     }
 
     private void setLocale(Locale locale) {
@@ -199,6 +207,7 @@
     public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
         for (int i = 0; i < mLength; i++) {
             if (mSpellCheckSpans[i] == spellCheckSpan) {
+                // Resets id and progress to invalidate spell check span
                 mSpellCheckSpans[i].setSpellCheckInProgress(false);
                 mIds[i] = -1;
                 return;
@@ -211,6 +220,9 @@
     }
 
     public void spellCheck(int start, int end) {
+        if (DBG) {
+            Log.d(TAG, "Start spell-checking: " + start + ", " + end);
+        }
         final Locale locale = mTextView.getTextServicesLocale();
         final boolean isSessionActive = isSessionActive();
         if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) {
@@ -238,6 +250,9 @@
             }
         }
 
+        if (DBG) {
+            Log.d(TAG, "new spell parser.");
+        }
         // No available parser found in pool, create a new one
         SpellParser[] newSpellParsers = new SpellParser[length + 1];
         System.arraycopy(mSpellParsers, 0, newSpellParsers, 0, length);
@@ -260,13 +275,22 @@
 
         for (int i = 0; i < mLength; i++) {
             final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
-            if (spellCheckSpan.isSpellCheckInProgress()) continue;
+            if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) continue;
 
             final int start = editable.getSpanStart(spellCheckSpan);
             final int end = editable.getSpanEnd(spellCheckSpan);
 
             // Do not check this word if the user is currently editing it
-            if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
+            final boolean isEditing;
+            if (mIsSentenceSpellCheckSupported) {
+                // Allow the overlap of the cursor and the first boundary of the spell check span
+                // no to skip the spell check of the following word because the
+                // following word will never be spell-checked even if the user finishes composing
+                isEditing = selectionEnd <= start || selectionStart > end;
+            } else {
+                isEditing = selectionEnd < start || selectionStart > end;
+            }
+            if (start >= 0 && end > start && isEditing) {
                 final String word = (editable instanceof SpannableStringBuilder) ?
                         ((SpannableStringBuilder) editable).substring(start, end) :
                         editable.subSequence(start, end).toString();
@@ -372,6 +396,9 @@
     }
 
     private void scheduleNewSpellCheck() {
+        if (DBG) {
+            Log.i(TAG, "schedule new spell check.");
+        }
         if (mSpellRunnable == null) {
             mSpellRunnable = new Runnable() {
                 @Override
@@ -423,6 +450,20 @@
 
         SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions,
                 SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+        // TODO: Remove mIsSentenceSpellCheckSupported by extracting an interface
+        // to share the logic of word level spell checker and sentence level spell checker
+        if (mIsSentenceSpellCheckSupported) {
+            final long key = TextUtils.packRangeInLong(start, end);
+            final SuggestionSpan tempSuggestionSpan = mSuggestionSpanCache.get(key);
+            if (tempSuggestionSpan != null) {
+                if (DBG) {
+                    Log.i(TAG, "Cached span on the same position is cleard. "
+                            + editable.subSequence(start, end));
+                }
+                editable.removeSpan(tempSuggestionSpan);
+            }
+            mSuggestionSpanCache.put(key, suggestionSpan);
+        }
         editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
         mTextView.invalidateRegion(start, end, false /* No cursor involved */);
@@ -447,10 +488,17 @@
         }
 
         private void setRangeSpan(Editable editable, int start, int end) {
+            if (DBG) {
+                Log.d(TAG, "set next range span: " + start + ", " + end);
+            }
             editable.setSpan(mRange, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         private void removeRangeSpan(Editable editable) {
+            if (DBG) {
+                Log.d(TAG, "Remove range span." + editable.getSpanStart(editable)
+                        + editable.getSpanEnd(editable));
+            }
             editable.removeSpan(mRange);
         }
 
@@ -484,6 +532,9 @@
                 wordEnd = mWordIterator.getEnd(wordStart);
             }
             if (wordEnd == BreakIterator.DONE) {
+                if (DBG) {
+                    Log.i(TAG, "No more spell check.");
+                }
                 removeRangeSpan(editable);
                 return;
             }
@@ -499,47 +550,72 @@
             boolean scheduleOtherSpellCheck = false;
 
             if (mIsSentenceSpellCheckSupported) {
-                int regionEnd;
                 if (wordIteratorWindowEnd < end) {
+                    if (DBG) {
+                        Log.i(TAG, "schedule other spell check.");
+                    }
                     // Several batches needed on that region. Cut after last previous word
-                    regionEnd = mWordIterator.preceding(wordIteratorWindowEnd);
                     scheduleOtherSpellCheck = true;
-                } else {
-                    regionEnd = mWordIterator.preceding(end);
                 }
-                boolean correct = regionEnd != BreakIterator.DONE;
+                int spellCheckEnd = mWordIterator.preceding(wordIteratorWindowEnd);
+                boolean correct = spellCheckEnd != BreakIterator.DONE;
                 if (correct) {
-                    regionEnd = mWordIterator.getEnd(regionEnd);
-                    correct = regionEnd != BreakIterator.DONE;
+                    spellCheckEnd = mWordIterator.getEnd(spellCheckEnd);
+                    correct = spellCheckEnd != BreakIterator.DONE;
                 }
                 if (!correct) {
-                    editable.removeSpan(mRange);
+                    if (DBG) {
+                        Log.i(TAG, "Incorrect range span.");
+                    }
+                    removeRangeSpan(editable);
                     return;
                 }
-                // Stop spell checking when there are no characters in the range.
-                if (wordEnd < start) {
-                    return;
-                }
-                // TODO: Find the start position of the sentence.
-                final int spellCheckStart =  wordStart;
-                if (regionEnd <= spellCheckStart) {
-                    return;
-                }
-                final int selectionStart = Selection.getSelectionStart(editable);
-                final int selectionEnd = Selection.getSelectionEnd(editable);
-                if (DBG) {
-                    Log.d(TAG, "addSpellCheckSpan: "
-                            + editable.subSequence(spellCheckStart, regionEnd)
-                            + ", regionEnd = " + regionEnd + ", spellCheckStart = "
-                            + spellCheckStart + ", sel start = " + selectionStart + ", sel end ="
-                            + selectionEnd);
-                }
-                // Do not check this word if the user is currently editing it
-                if (spellCheckStart >= 0 && regionEnd > spellCheckStart
-                        && (selectionEnd < spellCheckStart || selectionStart > regionEnd)) {
-                    addSpellCheckSpan(editable, spellCheckStart, regionEnd);
-                }
-                wordStart = regionEnd;
+                do {
+                    // TODO: Find the start position of the sentence.
+                    int spellCheckStart = wordStart;
+                    boolean createSpellCheckSpan = true;
+                    // Cancel or merge overlapped spell check spans
+                    for (int i = 0; i < mLength; ++i) {
+                        final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
+                        if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) {
+                            continue;
+                        }
+                        final int spanStart = editable.getSpanStart(spellCheckSpan);
+                        final int spanEnd = editable.getSpanEnd(spellCheckSpan);
+                        if (spanEnd < spellCheckStart || spellCheckEnd < spanStart) {
+                            // No need to merge
+                            continue;
+                        }
+                        if (spanStart <= spellCheckStart && spellCheckEnd <= spanEnd) {
+                            // There is a completely overlapped spell check span
+                            // skip this span
+                            createSpellCheckSpan = false;
+                            if (DBG) {
+                                Log.i(TAG, "The range is overrapped. Skip spell check.");
+                            }
+                            break;
+                        }
+                        removeSpellCheckSpan(spellCheckSpan);
+                        spellCheckStart = Math.min(spanStart, spellCheckStart);
+                        spellCheckEnd = Math.max(spanEnd, spellCheckEnd);
+                    }
+
+                    if (DBG) {
+                        Log.d(TAG, "addSpellCheckSpan: "
+                                + ", End = " + spellCheckEnd + ", Start = " + spellCheckStart
+                                + ", next = " + scheduleOtherSpellCheck + "\n"
+                                + editable.subSequence(spellCheckStart, spellCheckEnd));
+                    }
+
+                    // Stop spell checking when there are no characters in the range.
+                    if (spellCheckEnd < start) {
+                        break;
+                    }
+                    if (createSpellCheckSpan) {
+                        addSpellCheckSpan(editable, spellCheckStart, spellCheckEnd);
+                    }
+                } while (false);
+                wordStart = spellCheckEnd;
             } else {
                 while (wordStart <= end) {
                     if (wordEnd >= start && wordEnd > wordStart) {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 51bbdf1..4f2afa7 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -19,15 +19,17 @@
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LabeledIntent;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -38,8 +40,8 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
+import android.widget.Button;
+import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
@@ -56,12 +58,19 @@
  * which there is more than one matching activity, allowing the user to decide
  * which to go to.  It is not normally used directly by application developers.
  */
-public class ResolverActivity extends AlertActivity implements
-        DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
+public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {
+    private static final String TAG = "ResolverActivity";
+
     private ResolveListAdapter mAdapter;
-    private CheckBox mAlwaysCheck;
-    private TextView mClearDefaultHint;
     private PackageManager mPm;
+    private boolean mAlwaysUseOption;
+    private boolean mShowExtended;
+    private GridView mGrid;
+    private Button mAlwaysButton;
+    private Button mOnceButton;
+    private int mIconDpi;
+    private int mIconSize;
+    private int mMaxColumns;
 
     private boolean mRegistered;
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -91,33 +100,38 @@
     protected void onCreate(Bundle savedInstanceState, Intent intent,
             CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList,
             boolean alwaysUseOption) {
+        setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
         super.onCreate(savedInstanceState);
         mPm = getPackageManager();
+        mAlwaysUseOption = alwaysUseOption;
+        mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns);
         intent.setComponent(null);
 
         AlertController.AlertParams ap = mAlertParams;
 
         ap.mTitle = title;
-        ap.mOnClickListener = this;
 
         mPackageMonitor.register(this, getMainLooper(), false);
         mRegistered = true;
 
-        if (alwaysUseOption) {
-            LayoutInflater inflater = (LayoutInflater) getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            ap.mView = inflater.inflate(R.layout.always_use_checkbox, null);
-            mAlwaysCheck = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
-            mAlwaysCheck.setText(R.string.alwaysUse);
-            mAlwaysCheck.setOnCheckedChangeListener(this);
-            mClearDefaultHint = (TextView)ap.mView.findViewById(
-                                                        com.android.internal.R.id.clearDefaultHint);
-            mClearDefaultHint.setVisibility(View.GONE);
-        }
+        final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
+        mIconDpi = am.getLauncherLargeIconDensity();
+        mIconSize = am.getLauncherLargeIconSize();
+
         mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList);
         int count = mAdapter.getCount();
         if (count > 1) {
-            ap.mAdapter = mAdapter;
+            ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
+            mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
+            mGrid.setAdapter(mAdapter);
+            mGrid.setOnItemClickListener(this);
+            mGrid.setOnItemLongClickListener(new ItemLongClickListener());
+
+            if (alwaysUseOption) {
+                mGrid.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+            }
+
+            resizeGrid();
         } else if (count == 1) {
             startActivity(mAdapter.intentForPosition(0));
             mPackageMonitor.unregister();
@@ -125,17 +139,57 @@
             finish();
             return;
         } else {
-            ap.mMessage = getResources().getText(com.android.internal.R.string.noApplications);
+            ap.mMessage = getResources().getText(R.string.noApplications);
         }
 
         setupAlert();
 
-        ListView lv = mAlert.getListView();
-        if (lv != null) {
-            lv.setOnItemLongClickListener(new ItemLongClickListener());
+        if (alwaysUseOption) {
+            final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
+            buttonLayout.setVisibility(View.VISIBLE);
+            mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
+            mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
         }
     }
 
+    void resizeGrid() {
+        final int itemCount = mAdapter.getCount();
+        mGrid.setNumColumns(Math.min(itemCount, mMaxColumns));
+    }
+
+    Drawable getIcon(Resources res, int resId) {
+        Drawable result;
+        try {
+            result = res.getDrawableForDensity(resId, mIconDpi);
+        } catch (Resources.NotFoundException e) {
+            result = null;
+        }
+
+        return result;
+    }
+
+    Drawable loadIconForResolveInfo(ResolveInfo ri) {
+        Drawable dr;
+        try {
+            if (ri.resolvePackageName != null && ri.icon != 0) {
+                dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon);
+                if (dr != null) {
+                    return dr;
+                }
+            }
+            final int iconRes = ri.getIconResource();
+            if (iconRes != 0) {
+                dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes);
+                if (dr != null) {
+                    return dr;
+                }
+            }
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Couldn't find resources for package", e);
+        }
+        return ri.loadIcon(mPm);
+    }
+
     @Override
     protected void onRestart() {
         super.onRestart();
@@ -155,11 +209,28 @@
         }
     }
 
-    public void onClick(DialogInterface dialog, int which) {
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        if (mAlwaysUseOption) {
+            final int checkedPos = mGrid.getCheckedItemPosition();
+            final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+            mAlwaysButton.setEnabled(enabled);
+            mOnceButton.setEnabled(enabled);
+        } else {
+            startSelected(position, false);
+        }
+    }
+
+    public void onButtonClick(View v) {
+        final int id = v.getId();
+        startSelected(mGrid.getCheckedItemPosition(), id == R.id.button_always);
+        dismiss();
+    }
+
+    void startSelected(int which, boolean always) {
         ResolveInfo ri = mAdapter.resolveInfoForPosition(which);
         Intent intent = mAdapter.intentForPosition(which);
-        boolean alwaysCheck = (mAlwaysCheck != null && mAlwaysCheck.isChecked());
-        onIntentSelected(ri, intent, alwaysCheck);
+        onIntentSelected(ri, intent, always);
         finish();
     }
 
@@ -249,6 +320,12 @@
         }
     }
 
+    void showAppDetails(ResolveInfo ri) {
+        Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
+                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+        startActivity(in);
+    }
+
     private final class DisplayResolveInfo {
         ResolveInfo ri;
         CharSequence displayLabel;
@@ -285,12 +362,18 @@
         }
 
         public void handlePackagesChanged() {
+            final int oldItemCount = getCount();
             rebuildList();
             notifyDataSetChanged();
             if (mList.size() <= 0) {
                 // We no longer have any items...  just finish the activity.
                 finish();
             }
+
+            final int newItemCount = getCount();
+            if (newItemCount != oldItemCount) {
+                resizeGrid();
+            }
         }
 
         private void rebuildList() {
@@ -299,7 +382,7 @@
             } else {
                 mCurrentResolveList = mPm.queryIntentActivities(
                         mIntent, PackageManager.MATCH_DEFAULT_ONLY
-                        | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
+                        | (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0));
             }
             int N;
             if ((mCurrentResolveList != null) && ((N = mCurrentResolveList.size()) > 0)) {
@@ -363,6 +446,7 @@
                 r0 = mCurrentResolveList.get(0);
                 int start = 0;
                 CharSequence r0Label =  r0.loadLabel(mPm);
+                mShowExtended = false;
                 for (int i = 1; i < N; i++) {
                     if (r0Label == null) {
                         r0Label = r0.activityInfo.packageName;
@@ -393,6 +477,7 @@
                 // No duplicate labels. Use label for entry at start
                 mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
             } else {
+                mShowExtended = true;
                 boolean usePkg = false;
                 CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
                 if (startApp == null) {
@@ -473,6 +558,11 @@
             if (convertView == null) {
                 view = mInflater.inflate(
                         com.android.internal.R.layout.resolve_list_item, parent, false);
+
+                // Fix the icon size even if we have different sized resources
+                ImageView icon = (ImageView)view.findViewById(R.id.icon);
+                ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+                lp.width = lp.height = mIconSize;
             } else {
                 view = convertView;
             }
@@ -485,37 +575,25 @@
             TextView text2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
             ImageView icon = (ImageView)view.findViewById(R.id.icon);
             text.setText(info.displayLabel);
-            if (info.extendedInfo != null) {
+            if (mShowExtended) {
                 text2.setVisibility(View.VISIBLE);
                 text2.setText(info.extendedInfo);
             } else {
                 text2.setVisibility(View.GONE);
             }
             if (info.displayIcon == null) {
-                info.displayIcon = info.ri.loadIcon(mPm);
+                info.displayIcon = loadIconForResolveInfo(info.ri);
             }
             icon.setImageDrawable(info.displayIcon);
         }
     }
 
-    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        if (mClearDefaultHint == null) return;
-
-        if(isChecked) {
-            mClearDefaultHint.setVisibility(View.VISIBLE);
-        } else {
-            mClearDefaultHint.setVisibility(View.GONE);
-        }
-    }
-
     class ItemLongClickListener implements AdapterView.OnItemLongClickListener {
 
         @Override
         public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
             ResolveInfo ri = mAdapter.resolveInfoForPosition(position);
-            Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
-                    .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
-            startActivity(in);
+            showAppDetails(ri);
             return true;
         }
 
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index d5c2018..449194b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -70,8 +70,13 @@
         setOnClickListener(this);
         setOnLongClickListener(this);
 
-        // Save the inflated padding for later, we'll need it.
-        mSavedPaddingLeft = getPaddingLeft();
+        mSavedPaddingLeft = -1;
+    }
+
+    @Override
+    public void setPadding(int l, int t, int r, int b) {
+        mSavedPaddingLeft = l;
+        super.setPadding(l, t, r, b);
     }
 
     public MenuItemImpl getItemData() {
@@ -217,8 +222,9 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final boolean textVisible = hasText();
-        if (textVisible) {
-            setPadding(mSavedPaddingLeft, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+        if (textVisible && mSavedPaddingLeft >= 0) {
+            super.setPadding(mSavedPaddingLeft, getPaddingTop(),
+                    getPaddingRight(), getPaddingBottom());
         }
 
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -240,7 +246,7 @@
             // a little coercion. Pad in to center the icon after we've measured.
             final int w = getMeasuredWidth();
             final int dw = mIcon.getIntrinsicWidth();
-            setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+            super.setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
         }
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index af67d55..f54575b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -25,6 +26,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 
+import com.android.internal.R;
+
 /**
  * @hide
  */
@@ -43,6 +46,7 @@
     private int mMinCellSize;
     private int mGeneratedItemPadding;
     private int mMeasuredExtraWidth;
+    private int mMaxItemHeight;
 
     public ActionMenuView(Context context) {
         this(context, null);
@@ -54,6 +58,11 @@
         final float density = context.getResources().getDisplayMetrics().density;
         mMinCellSize = (int) (MIN_CELL_SIZE * density);
         mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
+                R.attr.actionBarStyle, 0);
+        mMaxItemHeight = a.getDimensionPixelSize(R.styleable.ActionBar_height, 0);
+        a.recycle();
     }
 
     public void setPresenter(ActionMenuPresenter presenter) {
@@ -116,6 +125,11 @@
         final int widthPadding = getPaddingLeft() + getPaddingRight();
         final int heightPadding = getPaddingTop() + getPaddingBottom();
 
+        final int itemHeightSpec = heightMode == MeasureSpec.EXACTLY
+                ? MeasureSpec.makeMeasureSpec(heightSize - heightPadding, MeasureSpec.EXACTLY)
+                : MeasureSpec.makeMeasureSpec(
+                    Math.min(mMaxItemHeight, heightSize - heightPadding), MeasureSpec.AT_MOST);
+
         widthSize -= widthPadding;
 
         // Divide the view into cells.
@@ -167,7 +181,7 @@
             final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
 
             final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
-                    heightMeasureSpec, heightPadding);
+                    itemHeightSpec, heightPadding);
 
             maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
             if (lp.expandable) expandableItemCount++;
@@ -298,7 +312,6 @@
 
         // Remeasure any items that have had extra space allocated to them.
         if (needsExpansion) {
-            int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode);
             for (int i = 0; i < childCount; i++) {
                 final View child = getChildAt(i);
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -306,7 +319,8 @@
                 if (!lp.expanded) continue;
 
                 final int width = lp.cellsUsed * cellSize + lp.extraPixels;
-                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec);
+                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                        itemHeightSpec);
             }
         }
 
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 47ed2c1..3a6c5b0 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -360,6 +360,9 @@
         // already have a pixelref installed.
         pr = bitmap->pixelRef();
     }
+    if (pr == NULL) {
+        return nullObjectReturn("Got null SkPixelRef");
+    }
 
     if (!isMutable) {
         // promise we will never change our pixels (great for sharing and pictures)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bd1f574..e16e49a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -155,9 +155,10 @@
          receiving or reading an MMS. -->
     <permission-group android:name="android.permission-group.MESSAGES"
         android:label="@string/permgrouplab_messages"
+        android:icon="@drawable/perm_group_messages"
         android:description="@string/permgroupdesc_messages"
         android:permissionGroupFlags="personalInfo"
-        android:priority="2"/>
+        android:priority="360"/>
 
   <!-- Allows an application to send SMS messages. -->
     <permission android:name="android.permission.SEND_SMS"
@@ -250,9 +251,10 @@
 
     <permission-group android:name="android.permission-group.SOCIAL_INFO"
         android:label="@string/permgrouplab_socialInfo"
+        android:icon="@drawable/perm_group_social_info"
         android:description="@string/permgroupdesc_socialInfo"
         android:permissionGroupFlags="personalInfo"
-        android:priority="6" />
+        android:priority="320" />
 
     <!-- Allows an application to read the user's contacts data. -->
     <permission android:name="android.permission.READ_CONTACTS"
@@ -310,9 +312,10 @@
          distinct permissions). -->
     <permission-group android:name="android.permission-group.PERSONAL_INFO"
         android:label="@string/permgrouplab_personalInfo"
+        android:icon="@drawable/perm_group_personal_info"
         android:description="@string/permgroupdesc_personalInfo"
         android:permissionGroupFlags="personalInfo"
-        android:priority="7" />
+        android:priority="310" />
 
     <!-- Allows an application to read the user's personal profile data. -->
     <permission android:name="android.permission.READ_PROFILE"
@@ -338,9 +341,10 @@
          calendar to create / view events.-->
     <permission-group android:name="android.permission-group.CALENDAR"
         android:label="@string/permgrouplab_calendar"
+        android:icon="@drawable/perm_group_calendar"
         android:description="@string/permgroupdesc_calendar"
         android:permissionGroupFlags="personalInfo"
-        android:priority="9" />
+        android:priority="290" />
 
     <!-- Allows an application to read the user's calendar data. -->
     <permission android:name="android.permission.READ_CALENDAR"
@@ -366,9 +370,10 @@
          calendar to create / view events.-->
     <permission-group android:name="android.permission-group.USER_DICTIONARY"
         android:label="@string/permgrouplab_dictionary"
+        android:icon="@drawable/perm_group_user_dictionary"
         android:description="@string/permgroupdesc_dictionary"
         android:permissionGroupFlags="personalInfo"
-        android:priority="20" />
+        android:priority="170" />
 
     <!-- Allows an application to read the user dictionary. This should
          really only be required by an IME, or a dictionary editor like
@@ -379,9 +384,18 @@
         android:label="@string/permlab_readDictionary"
         android:description="@string/permdesc_readDictionary" />
 
+    <!-- Used for permissions that provide access to the user
+         calendar to create / view events.-->
+    <permission-group android:name="android.permission-group.WRITE_USER_DICTIONARY"
+        android:label="@string/permgrouplab_writeDictionary"
+        android:icon="@drawable/perm_group_user_dictionary_write"
+        android:description="@string/permgroupdesc_writeDictionary"
+        android:permissionGroupFlags="personalInfo"
+        android:priority="160" />
+
     <!-- Allows an application to write to the user dictionary. -->
     <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-        android:permissionGroup="android.permission-group.USER_DICTIONARY"
+        android:permissionGroup="android.permission-group.WRITE_USER_DICTIONARY"
         android:protectionLevel="normal"
         android:label="@string/permlab_writeDictionary"
         android:description="@string/permdesc_writeDictionary" />
@@ -395,9 +409,10 @@
          bookmarks and browser history.-->
     <permission-group android:name="android.permission-group.BOOKMARKS"
         android:label="@string/permgrouplab_bookmarks"
+        android:icon="@drawable/perm_group_bookmarks"
         android:description="@string/permgroupdesc_bookmarks"
         android:permissionGroupFlags="personalInfo"
-        android:priority="8" />
+        android:priority="300" />
 
     <!-- Allows an application to read (but not write) the user's
         browsing history and bookmarks. -->
@@ -423,9 +438,10 @@
     <!-- Used for permissions that provide access to the user voicemail box. -->
     <permission-group android:name="android.permission-group.DEVICE_ALARMS"
         android:label="@string/permgrouplab_deviceAlarms"
+        android:icon="@drawable/perm_group_device_alarms"
         android:description="@string/permgroupdesc_deviceAlarms"
         android:permissionGroupFlags="personalInfo"
-        android:priority="16"/>
+        android:priority="210" />
 
     <!-- Allows an application to broadcast an Intent to set an alarm for the
          user. -->
@@ -443,9 +459,10 @@
     <!-- Used for permissions that provide access to the user voicemail box. -->
     <permission-group android:name="android.permission-group.VOICEMAIL"
         android:label="@string/permgrouplab_voicemail"
+        android:icon="@drawable/perm_group_voicemail"
         android:description="@string/permgroupdesc_voicemail"
         android:permissionGroupFlags="personalInfo"
-        android:priority="10" />
+        android:priority="280" />
 
    <!-- Allows an application to add voicemails into the system. -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
@@ -463,9 +480,10 @@
          location. -->
     <permission-group android:name="android.permission-group.LOCATION"
         android:label="@string/permgrouplab_location"
+        android:icon="@drawable/perm_group_location"
         android:description="@string/permgroupdesc_location"
         android:permissionGroupFlags="personalInfo"
-        android:priority="5" />
+        android:priority="330" />
 
     <!-- Allows an application to access fine (e.g., GPS) location -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
@@ -512,8 +530,9 @@
          or other related network operations. -->
     <permission-group android:name="android.permission-group.NETWORK"
         android:label="@string/permgrouplab_network"
+        android:icon="@drawable/perm_group_network"
         android:description="@string/permgroupdesc_network"
-        android:priority="11" />
+        android:priority="270" />
 
     <!-- Allows applications to open network sockets. -->
     <permission android:name="android.permission.INTERNET"
@@ -562,28 +581,36 @@
     <!-- ======================================= -->
     <eat-comment />
 
-    <!-- Used for permissions that provide access to network services that
-         are for peripherals and other nearby devices.  These networks
-         generally do not provide IP based networking or internet access.-->
-    <permission-group android:name="android.permission-group.SHORTRANGE_NETWORK"
-        android:label="@string/permgrouplab_shortRangeNetwork"
-        android:description="@string/permgroupdesc_shortRangeNetwork"
-        android:priority="12" />
+    <!-- Used for permissions that provide access to other devices through Bluetooth.-->
+    <permission-group android:name="android.permission-group.BLUETOOTH_NETWORK"
+        android:label="@string/permgrouplab_bluetoothNetwork"
+        android:icon="@drawable/perm_group_bluetooth"
+        android:description="@string/permgroupdesc_bluetoothNetwork"
+        android:priority="260" />
 
     <!-- Allows applications to connect to paired bluetooth devices -->
     <permission android:name="android.permission.BLUETOOTH"
-        android:permissionGroup="android.permission-group.SHORTRANGE_NETWORK"
+        android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK"
         android:protectionLevel="dangerous"
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
         
     <!-- Allows applications to discover and pair bluetooth devices -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
-        android:permissionGroup="android.permission-group.SHORTRANGE_NETWORK"
+        android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK"
         android:protectionLevel="dangerous"
         android:description="@string/permdesc_bluetoothAdmin"
         android:label="@string/permlab_bluetoothAdmin" />
    
+    <!-- Used for permissions that provide access to network services that
+         are for peripherals and other nearby devices.  These networks
+         generally do not provide IP based networking or internet access.-->
+    <permission-group android:name="android.permission-group.SHORTRANGE_NETWORK"
+        android:label="@string/permgrouplab_shortrangeNetwork"
+        android:icon="@drawable/perm_group_shortrange_network"
+        android:description="@string/permgroupdesc_shortrangeNetwork"
+        android:priority="250" />
+
     <!-- Allows applications to perform I/O operations over NFC -->
     <permission android:name="android.permission.NFC"
         android:permissionGroup="android.permission-group.SHORTRANGE_NETWORK"
@@ -607,9 +634,10 @@
          by the Account Manager. -->
     <permission-group android:name="android.permission-group.ACCOUNTS"
         android:label="@string/permgrouplab_accounts"
+        android:icon="@drawable/perm_group_accounts"
         android:description="@string/permgroupdesc_accounts"
         android:permissionGroupFlags="personalInfo"
-        android:priority="17" />
+        android:priority="200" />
 
     <!-- Allows access to the list of accounts in the Accounts Service -->
     <permission android:name="android.permission.GET_ACCOUNTS"
@@ -659,8 +687,9 @@
 
     <permission-group android:name="android.permission-group.AFFECTS_BATTERY"
         android:label="@string/permgrouplab_affectsBattery"
+        android:icon="@drawable/perm_group_affects_battery"
         android:description="@string/permgroupdesc_affectsBattery"
-        android:priority="19" />
+        android:priority="180" />
 
     <!-- Allows applications to enter Wi-Fi Multicast mode -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
@@ -699,8 +728,9 @@
          the device. -->
     <permission-group android:name="android.permission-group.AUDIO_SETTINGS"
         android:label="@string/permgrouplab_audioSettings"
+        android:icon="@drawable/perm_group_audio_settings"
         android:description="@string/permgroupdesc_audioSettings"
-        android:priority="25" />
+        android:priority="130" />
 
     <!-- Allows an application to modify global audio settings -->
     <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
@@ -719,7 +749,7 @@
     <permission-group android:name="android.permission-group.HARDWARE_CONTROLS"
         android:label="@string/permgrouplab_hardwareControls"
         android:description="@string/permgroupdesc_hardwareControls"
-        android:priority="26"/>
+        android:priority="260"/>
 
     <!-- Allows an application to manage preferences and permissions for USB devices
          @hide -->
@@ -766,9 +796,10 @@
          but are in a separate (more visible) permission group. -->
     <permission-group android:name="android.permission-group.MICROPHONE"
         android:label="@string/permgrouplab_microphone"
+        android:icon="@drawable/perm_group_microphone"
         android:description="@string/permgroupdesc_microphone"
         android:permissionGroupFlags="personalInfo"
-        android:priority="4" />
+        android:priority="340" />
 
     <!-- Allows an application to record audio -->
     <permission android:name="android.permission.RECORD_AUDIO"
@@ -786,9 +817,10 @@
          camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.CAMERA"
         android:label="@string/permgrouplab_camera"
+        android:icon="@drawable/perm_group_camera"
         android:description="@string/permgroupdesc_camera"
         android:permissionGroupFlags="personalInfo"
-        android:priority="3" />
+        android:priority="350" />
 
     <!-- Required to be able to access the camera device.
          <p>This will automatically enforce the <a
@@ -813,9 +845,10 @@
          and modifying the phone state. -->
     <permission-group android:name="android.permission-group.PHONE_CALLS"
         android:label="@string/permgrouplab_phoneCalls"
+        android:icon="@drawable/perm_group_phone_calls"
         android:description="@string/permgroupdesc_phoneCalls"
         android:permissionGroupFlags="personalInfo"
-        android:priority="1" />
+        android:priority="370" />
 
     <!-- Allows an application to monitor, modify, or abort outgoing
          calls. -->
@@ -870,9 +903,10 @@
     <!-- Group of permissions that are related to SD card access. -->
     <permission-group android:name="android.permission-group.STORAGE"
         android:label="@string/permgrouplab_storage"
+        android:icon="@drawable/perm_group_storage"
         android:description="@string/permgroupdesc_storage"
         android:permissionGroupFlags="personalInfo"
-        android:priority="13" />
+        android:priority="240" />
 
     <!-- Allows an application to read from external storage -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
@@ -904,8 +938,10 @@
     <!-- Group of permissions that are related to the screenlock. -->
     <permission-group android:name="android.permission-group.SCREENLOCK"
         android:label="@string/permgrouplab_storage"
+        android:icon="@drawable/perm_group_screenlock"
         android:permissionGroupFlags="personalInfo"
-        android:description="@string/permgroupdesc_storage" />
+        android:description="@string/permgroupdesc_storage"
+        android:priority="230" />
 
     <!-- Allows applications to disable the keyguard -->
     <permission android:name="android.permission.DISABLE_KEYGUARD"
@@ -924,7 +960,9 @@
          running apps, or killing background processes. -->
     <permission-group android:name="android.permission-group.APP_INFO"
         android:label="@string/permgrouplab_appInfo"
-        android:description="@string/permgroupdesc_appInfo" />
+        android:icon="@drawable/perm_group_app_info"
+        android:description="@string/permgroupdesc_appInfo"
+        android:priority="220" />
 
     <!-- Allows an application to get information about the currently
          or recently running tasks. -->
@@ -990,8 +1028,9 @@
          another application displays UI to the user. -->
     <permission-group android:name="android.permission-group.DISPLAY"
         android:label="@string/permgrouplab_display"
+        android:icon="@drawable/perm_group_display"
         android:description="@string/permgroupdesc_display"
-        android:priority="18"/>
+        android:priority="190"/>
 
     <!-- Allows an application to open windows using the type
          {@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
@@ -1013,8 +1052,9 @@
          another application displays UI to the user. -->
     <permission-group android:name="android.permission-group.WALLPAPER"
         android:label="@string/permgrouplab_wallpaper"
+        android:icon="@drawable/perm_group_wallpaper"
         android:description="@string/permgroupdesc_wallpaper"
-        android:priority="22" />
+        android:priority="150" />
 
     <!-- Allows applications to set the wallpaper -->
     <permission android:name="android.permission.SET_WALLPAPER"
@@ -1038,8 +1078,9 @@
     <!-- Group of permissions that are related to system clock. -->
     <permission-group android:name="android.permission-group.SYSTEM_CLOCK"
         android:label="@string/permgrouplab_systemClock"
+        android:icon="@drawable/perm_group_system_clock"
         android:description="@string/permgroupdesc_systemClock"
-        android:priority="23" />
+        android:priority="140" />
 
     <!-- Allows applications to set the system time -->
     <permission android:name="android.permission.SET_TIME"
@@ -1061,7 +1102,9 @@
     <!-- Used for permissions that change the status bar -->
     <permission-group android:name="android.permission-group.STATUS_BAR"
         android:label="@string/permgrouplab_statusBar"
-        android:description="@string/permgroupdesc_statusBar" />
+        android:icon="@drawable/perm_group_status_bar"
+        android:description="@string/permgroupdesc_statusBar"
+        android:priority="110" />
 
     <!-- Allows an application to expand or collapse the status bar. -->
     <permission android:name="android.permission.EXPAND_STATUS_BAR"
@@ -1078,8 +1121,9 @@
          related information. -->
     <permission-group android:name="android.permission-group.SYNC_SETTINGS"
         android:label="@string/permgrouplab_syncSettings"
+        android:icon="@drawable/perm_group_sync_settings"
         android:description="@string/permgroupdesc_syncSettings"
-        android:priority="29" />
+        android:priority="120" />
 
     <!-- Allows applications to read the sync settings -->
     <permission android:name="android.permission.READ_SYNC_SETTINGS"
@@ -1116,8 +1160,9 @@
          such as writing the global system settings. -->
     <permission-group android:name="android.permission-group.SYSTEM_TOOLS"
         android:label="@string/permgrouplab_systemTools"
+        android:icon="@drawable/perm_group_system_tools"
         android:description="@string/permgroupdesc_systemTools"
-        android:priority="30" />
+        android:priority="100" />
 
     <!-- @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
@@ -1345,7 +1390,7 @@
     <permission-group android:name="android.permission-group.DEVELOPMENT_TOOLS"
         android:label="@string/permgrouplab_developmentTools"
         android:description="@string/permgroupdesc_developmentTools"
-        android:priority="31" />
+        android:priority="310" />
 
     <!-- Allows an application to read or write the secure system settings. -->
     <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
diff --git a/core/res/res/drawable-hdpi/perm_group_accounts.png b/core/res/res/drawable-hdpi/perm_group_accounts.png
new file mode 100644
index 0000000..db59ab0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_affects_battery.png b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
new file mode 100644
index 0000000..8ca8154
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_app_info.png b/core/res/res/drawable-hdpi/perm_group_app_info.png
new file mode 100644
index 0000000..b03e2f3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_audio_settings.png b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
new file mode 100644
index 0000000..4e652a8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bluetooth.png b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
new file mode 100644
index 0000000..0f28454
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bookmarks.png b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
new file mode 100644
index 0000000..06f63445
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_calendar.png b/core/res/res/drawable-hdpi/perm_group_calendar.png
new file mode 100644
index 0000000..c0a4dfd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_camera.png b/core/res/res/drawable-hdpi/perm_group_camera.png
new file mode 100644
index 0000000..cbc07b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_device_alarms.png b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
new file mode 100644
index 0000000..d44b9de
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_display.png b/core/res/res/drawable-hdpi/perm_group_display.png
new file mode 100644
index 0000000..e8afece
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_location.png b/core/res/res/drawable-hdpi/perm_group_location.png
new file mode 100644
index 0000000..dc2f8ef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_messages.png b/core/res/res/drawable-hdpi/perm_group_messages.png
new file mode 100644
index 0000000..680c178
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_microphone.png b/core/res/res/drawable-hdpi/perm_group_microphone.png
new file mode 100644
index 0000000..a73a945
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_network.png b/core/res/res/drawable-hdpi/perm_group_network.png
new file mode 100644
index 0000000..c750e2aa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_personal_info.png b/core/res/res/drawable-hdpi/perm_group_personal_info.png
new file mode 100644
index 0000000..130e7ad
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_phone_calls.png b/core/res/res/drawable-hdpi/perm_group_phone_calls.png
new file mode 100644
index 0000000..577855b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_screenlock.png b/core/res/res/drawable-hdpi/perm_group_screenlock.png
new file mode 100644
index 0000000..9c5143d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_shortrange_network.png b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
new file mode 100644
index 0000000..554a4e4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_social_info.png b/core/res/res/drawable-hdpi/perm_group_social_info.png
new file mode 100644
index 0000000..134990b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_status_bar.png b/core/res/res/drawable-hdpi/perm_group_status_bar.png
new file mode 100644
index 0000000..bda963b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_storage.png b/core/res/res/drawable-hdpi/perm_group_storage.png
new file mode 100644
index 0000000..e6b3965
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_sync_settings.png b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
new file mode 100644
index 0000000..be70866
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_clock.png b/core/res/res/drawable-hdpi/perm_group_system_clock.png
new file mode 100644
index 0000000..75794c3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_tools.png b/core/res/res/drawable-hdpi/perm_group_system_tools.png
new file mode 100644
index 0000000..3fd4385
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
new file mode 100644
index 0000000..98a0894
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
new file mode 100644
index 0000000..784ea0f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_voicemail.png b/core/res/res/drawable-hdpi/perm_group_voicemail.png
new file mode 100644
index 0000000..b08b153
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_wallpaper.png b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
new file mode 100644
index 0000000..cf073a4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_accounts.png b/core/res/res/drawable-mdpi/perm_group_accounts.png
new file mode 100644
index 0000000..3dd4043
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_affects_battery.png b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
new file mode 100644
index 0000000..7291916
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_app_info.png b/core/res/res/drawable-mdpi/perm_group_app_info.png
new file mode 100644
index 0000000..8ba65bd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_audio_settings.png b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
new file mode 100644
index 0000000..f2f461b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bluetooth.png b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
new file mode 100644
index 0000000..6db6fde
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bookmarks.png b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
new file mode 100644
index 0000000..f908e14
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_calendar.png b/core/res/res/drawable-mdpi/perm_group_calendar.png
new file mode 100644
index 0000000..5905973
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_camera.png b/core/res/res/drawable-mdpi/perm_group_camera.png
new file mode 100644
index 0000000..be1c9e6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_device_alarms.png b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
new file mode 100644
index 0000000..48d6d6a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_display.png b/core/res/res/drawable-mdpi/perm_group_display.png
new file mode 100644
index 0000000..e10609c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_location.png b/core/res/res/drawable-mdpi/perm_group_location.png
new file mode 100644
index 0000000..e79ec25
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_messages.png b/core/res/res/drawable-mdpi/perm_group_messages.png
new file mode 100644
index 0000000..dfb3ba7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_microphone.png b/core/res/res/drawable-mdpi/perm_group_microphone.png
new file mode 100644
index 0000000..9bab315
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_network.png b/core/res/res/drawable-mdpi/perm_group_network.png
new file mode 100644
index 0000000..f2798a7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_personal_info.png b/core/res/res/drawable-mdpi/perm_group_personal_info.png
new file mode 100644
index 0000000..6233a82
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_phone_calls.png b/core/res/res/drawable-mdpi/perm_group_phone_calls.png
new file mode 100644
index 0000000..ff3ffd5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_screenlock.png b/core/res/res/drawable-mdpi/perm_group_screenlock.png
new file mode 100644
index 0000000..abfe6e4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_shortrange_network.png b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
new file mode 100644
index 0000000..5d73375
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_social_info.png b/core/res/res/drawable-mdpi/perm_group_social_info.png
new file mode 100644
index 0000000..c862f9e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_status_bar.png b/core/res/res/drawable-mdpi/perm_group_status_bar.png
new file mode 100644
index 0000000..4158fa6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_storage.png b/core/res/res/drawable-mdpi/perm_group_storage.png
new file mode 100644
index 0000000..3dcfb22
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_sync_settings.png b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
new file mode 100644
index 0000000..5a0e5ff
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_clock.png b/core/res/res/drawable-mdpi/perm_group_system_clock.png
new file mode 100644
index 0000000..e4d5743
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_tools.png b/core/res/res/drawable-mdpi/perm_group_system_tools.png
new file mode 100644
index 0000000..fc7337d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
new file mode 100644
index 0000000..92864ba
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
new file mode 100644
index 0000000..9f48713
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_voicemail.png b/core/res/res/drawable-mdpi/perm_group_voicemail.png
new file mode 100644
index 0000000..a34d689
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_wallpaper.png b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
new file mode 100644
index 0000000..b990e7f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_accounts.png b/core/res/res/drawable-xhdpi/perm_group_accounts.png
new file mode 100644
index 0000000..74cd33b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
new file mode 100644
index 0000000..d4a9bb5d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_app_info.png b/core/res/res/drawable-xhdpi/perm_group_app_info.png
new file mode 100644
index 0000000..46089e5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
new file mode 100644
index 0000000..2f7cbc3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
new file mode 100644
index 0000000..6bbde52
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
new file mode 100644
index 0000000..1277d03
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_calendar.png b/core/res/res/drawable-xhdpi/perm_group_calendar.png
new file mode 100644
index 0000000..3c7f2d3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_camera.png b/core/res/res/drawable-xhdpi/perm_group_camera.png
new file mode 100644
index 0000000..a454554
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
new file mode 100644
index 0000000..1bb151c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_display.png b/core/res/res/drawable-xhdpi/perm_group_display.png
new file mode 100644
index 0000000..9e36cf8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_location.png b/core/res/res/drawable-xhdpi/perm_group_location.png
new file mode 100644
index 0000000..4c49521
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_messages.png b/core/res/res/drawable-xhdpi/perm_group_messages.png
new file mode 100644
index 0000000..f046d46
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_microphone.png b/core/res/res/drawable-xhdpi/perm_group_microphone.png
new file mode 100644
index 0000000..bdb66e2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_network.png b/core/res/res/drawable-xhdpi/perm_group_network.png
new file mode 100644
index 0000000..fe1adad
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_personal_info.png b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
new file mode 100644
index 0000000..1ae418f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_phone_calls.png b/core/res/res/drawable-xhdpi/perm_group_phone_calls.png
new file mode 100644
index 0000000..288e15c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_screenlock.png b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
new file mode 100644
index 0000000..bf3ec34
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
new file mode 100644
index 0000000..5e1e240
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_social_info.png b/core/res/res/drawable-xhdpi/perm_group_social_info.png
new file mode 100644
index 0000000..2111a83
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_status_bar.png b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
new file mode 100644
index 0000000..ce65380
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_storage.png b/core/res/res/drawable-xhdpi/perm_group_storage.png
new file mode 100644
index 0000000..4cd5c9b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
new file mode 100644
index 0000000..24eb579
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_clock.png b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
new file mode 100644
index 0000000..36d1294
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_tools.png b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
new file mode 100644
index 0000000..7b6cdd8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
new file mode 100644
index 0000000..c0106bb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
new file mode 100644
index 0000000..36bb395
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_voicemail.png b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
new file mode 100644
index 0000000..eb17a63
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
new file mode 100644
index 0000000..be4663c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/layout/app_permission_item.xml b/core/res/res/layout/app_permission_item.xml
index 9b8c5ae..c448bd1 100644
--- a/core/res/res/layout/app_permission_item.xml
+++ b/core/res/res/layout/app_permission_item.xml
@@ -42,6 +42,7 @@
     <TextView
         android:id="@+id/perm_name"
         android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textSize="16sp"
         android:layout_marginLeft="8dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index c0404be..abeb7ba 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -18,39 +18,40 @@
 */
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:gravity="center_vertical"
-    android:orientation="horizontal"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip">
+              android:gravity="center"
+              android:orientation="vertical"
+              android:layout_height="wrap_content"
+              android:layout_width="match_parent"
+              android:background="?android:attr/activatedBackgroundIndicator"
+              android:padding="16dp">
 
-    <!-- Activity icon when presenting dialog -->
+    <!-- Extended activity info to distinguish between duplicate activity names -->
+    <TextView android:id="@android:id/text2"
+              android:textAppearance="?android:attr/textAppearance"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:gravity="center"
+              android:minLines="2"
+              android:maxLines="2"
+              android:paddingLeft="4dip"
+              android:paddingRight="4dip" />
+
+    <!-- Activity icon when presenting dialog
+         Size will be filled in by ResolverActivity -->
     <ImageView android:id="@+id/icon"
-        android:layout_width="@android:dimen/app_icon_size"
-        android:layout_height="@android:dimen/app_icon_size"
-        android:scaleType="fitCenter" />
+               android:layout_width="0dp"
+               android:layout_height="0dp"
+               android:scaleType="fitCenter" />
 
-    <LinearLayout
-        android:orientation="vertical"
-        android:gravity="center_vertical"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" >
-        <!-- Activity name -->
-        <TextView android:id="@android:id/text1"
-            android:textAppearance="?android:attr/textAppearanceListItemSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:maxLines="2"
-            android:paddingLeft="16dip" />
-        <!-- Extended activity info to distinguish between duplicate activity names -->
-        <TextView android:id="@android:id/text2"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:maxLines="2"
-            android:paddingLeft="16dip" />
-    </LinearLayout>
+    <!-- Activity name -->
+    <TextView android:id="@android:id/text1"
+              android:textAppearance="?android:attr/textAppearanceSmall"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:gravity="center"
+              android:minLines="2"
+              android:maxLines="2"
+              android:paddingLeft="4dip"
+              android:paddingRight="4dip" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_grid.xml
new file mode 100644
index 0000000..f10a59f0
--- /dev/null
+++ b/core/res/res/layout/resolver_grid.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2012, 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:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:divider="?android:attr/dividerHorizontal"
+              android:showDividers="middle"
+              android:dividerPadding="0dip">
+    <GridView
+        android:layout_gravity="center"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:id="@+id/resolver_grid"
+        android:numColumns="4"
+        android:columnWidth="128dp"
+        android:padding="16dp"
+        android:clipToPadding="false" />
+    <LinearLayout
+        android:id="@+id/button_bar"
+        android:visibility="gone"
+        style="?android:attr/buttonBarStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layoutDirection="locale"
+        android:measureWithLargestChild="true">
+        <Button android:id="@+id/button_always"
+                android:layout_width="wrap_content"
+                android:layout_gravity="right"
+                android:layout_weight="1"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?android:attr/buttonBarButtonStyle"
+                android:textSize="14sp"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_always"
+                android:onClick="onButtonClick" />
+        <Button android:id="@+id/button_once"
+                android:layout_width="wrap_content"
+                android:layout_gravity="left"
+                android:layout_weight="1"
+                android:maxLines="2"
+                style="?android:attr/buttonBarButtonStyle"
+                android:textSize="14sp"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_once"
+                android:onClick="onButtonClick" />
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index 864675a..8cd614d 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -24,10 +24,6 @@
     <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
     <dimen name="password_keyboard_height">48.0mm</dimen>
 
-    <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">230dp</dimen>
-    <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">135dp</dimen>
     <!-- Minimum width of the search view text entry area. -->
     <dimen name="search_view_text_min_width">192dip</dimen>
 
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 7fa7658..b54e9d1 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -35,5 +35,10 @@
     <!-- If true, the screen can be rotated via the accelerometer in all 4
          rotations as the default behavior. -->
     <bool name="config_allowAllRotations">true</bool>
+
+    <!-- Maximum number of grid columns permitted in the ResolverActivity
+         used for picking activities to handle an intent. -->
+    <integer name="config_maxResolverActivityColumns">3</integer>
+
 </resources>
 
diff --git a/core/res/res/values-sw720dp/config.xml b/core/res/res/values-sw720dp/config.xml
new file mode 100644
index 0000000..9792835
--- /dev/null
+++ b/core/res/res/values-sw720dp/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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>
+
+    <!-- Maximum number of grid columns permitted in the ResolverActivity
+         used for picking activities to handle an intent. -->
+    <integer name="config_maxResolverActivityColumns">4</integer>
+
+</resources>
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index bbbfaae..7b1bc4c5 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -34,6 +34,10 @@
          (the screen is in landscape). This may be either a fraction or a dimension.-->
     <item type="dimen" name="dialog_fixed_height_minor">90%</item>
 
+    <!-- The width that is used when creating thumbnails of applications. -->
+    <dimen name="thumbnail_width">230dp</dimen>
+    <!-- The height that is used when creating thumbnails of applications. -->
+    <dimen name="thumbnail_height">135dp</dimen>
 </resources>
 
 
diff --git a/core/res/res/values-w500dp/bools.xml b/core/res/res/values-w500dp/bools.xml
new file mode 100644
index 0000000..f53fd39
--- /dev/null
+++ b/core/res/res/values-w500dp/bools.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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>
+    <bool name="activity_chooser_view_has_default_activity">true</bool>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-xlarge/dimens.xml b/core/res/res/values-xlarge/dimens.xml
index c15770d..29cea26 100644
--- a/core/res/res/values-xlarge/dimens.xml
+++ b/core/res/res/values-xlarge/dimens.xml
@@ -25,10 +25,6 @@
     <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
     <dimen name="password_keyboard_height">48.0mm</dimen>
 
-    <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">230dp</dimen>
-    <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">135dp</dimen>
     <!-- Minimum width of the search view text entry area. -->
     <dimen name="search_view_text_min_width">192dip</dimen>
 
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index f9762b1..6910ebe 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -22,4 +22,5 @@
     <bool name="show_ongoing_ime_switcher">true</bool>
     <bool name="action_bar_expanded_action_views_exclusive">true</bool>
     <bool name="target_honeycomb_needs_options_menu">true</bool>
+    <bool name="activity_chooser_view_has_default_activity">false</bool>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 229f518..5fa7b7e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -846,6 +846,10 @@
          movement threshold where scrolling should begin. -->
     <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>
 
+    <!-- Maximum number of grid columns permitted in the ResolverActivity
+         used for picking activities to handle an intent. -->
+    <integer name="config_maxResolverActivityColumns">2</integer>
+
     <!-- Array of OEM specific USB mode override config.
          OEM can override a certain USB mode depending on ro.bootmode.
          Specify an array of below items to set override rule.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f06e30f..98c19cf 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -462,7 +462,6 @@
   <java-symbol type="string" name="db_default_sync_mode" />
   <java-symbol type="string" name="db_wal_sync_mode" />
   <java-symbol type="string" name="decline" />
-  <java-symbol type="string" name="default_permission_group" />
   <java-symbol type="string" name="default_text_encoding" />
   <java-symbol type="string" name="description_target_unlock_tablet" />
   <java-symbol type="string" name="double_tap_toast" />
@@ -652,10 +651,8 @@
   <java-symbol type="string" name="orgTypeOther" />
   <java-symbol type="string" name="orgTypeWork" />
   <java-symbol type="string" name="passwordIncorrect" />
-  <java-symbol type="string" name="permissions_format" />
+  <java-symbol type="string" name="perms_description_app" />
   <java-symbol type="string" name="perms_new_perm_prefix" />
-  <java-symbol type="string" name="perms_hide" />
-  <java-symbol type="string" name="perms_show_all" />
   <java-symbol type="string" name="petabyteShort" />
   <java-symbol type="string" name="phoneTypeAssistant" />
   <java-symbol type="string" name="phoneTypeCallback" />
@@ -1376,6 +1373,7 @@
   <java-symbol type="bool" name="config_wifi_dual_band_support" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
+  <java-symbol type="bool" name="activity_chooser_view_has_default_activity" />
   <java-symbol type="color" name="config_defaultNotificationColor" />
   <java-symbol type="drawable" name="ic_notification_ime_default" />
   <java-symbol type="drawable" name="stat_notify_car_mode" />
@@ -1510,6 +1508,12 @@
   <java-symbol type="bool" name="config_enableDreams" />
   <java-symbol type="string" name="config_defaultDreamComponent" />
 
+  <java-symbol type="layout" name="resolver_grid" />
+  <java-symbol type="id" name="resolver_grid" />
+  <java-symbol type="id" name="button_once" />
+  <java-symbol type="id" name="button_always" />
+  <java-symbol type="integer" name="config_maxResolverActivityColumns" />
+
   <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
   <java-symbol type="anim" name="push_down_out" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3250507..e7ad4c2 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -408,16 +408,21 @@
     <string name="permgroupdesc_network">Access various network features.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_shortRangeNetwork">Bluetooth and NFC</string>
+    <string name="permgrouplab_bluetoothNetwork">Bluetooth</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_shortRangeNetwork">Access Bluetooth or NFC networks and devices.</string>
+    <string name="permgroupdesc_bluetoothNetwork">Access devices and networks through Bluetooth.</string>
 
-  <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_shortrangeNetwork">Short-range Networks</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_shortrangeNetwork">Access devices through short-range networks such as NFC.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_audioSettings">Audio Settings</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_audioSettings">Change audio settings.</string>
 
-  <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_affectsBattery">Affects Battery</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_affectsBattery">Use features that can quickly drain battery.</string>
@@ -428,9 +433,14 @@
     <string name="permgroupdesc_calendar">Direct access to calendar and events.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_dictionary">User Dictionary</string>
+    <string name="permgrouplab_dictionary">Read User Dictionary</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_dictionary">Direct access to the user dictionary.</string>
+    <string name="permgroupdesc_dictionary">Read words in user dictionary.</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_writeDictionary">Write User Dictionary</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_writeDictionary">Add words to the user dictionary.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_bookmarks">Bookmarks and History</string>
@@ -1597,7 +1607,7 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
     <string name="permlab_sdcardWrite" product="nosdcard">modify or delete the contents of your USB storage</string>
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_sdcardWrite" product="default">modify or delete the contens of your SD card</string>
+    <string name="permlab_sdcardWrite" product="default">modify or delete the contents of your SD card</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
     <string name="permdesc_sdcardWrite" product="nosdcard">Allows the app to write to the USB storage.</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2976,18 +2986,12 @@
     <string name="date_time_done">Done</string>
 
     <!-- Security Permissions strings-->
-    <!-- The default permission group for any permissions that have not explicitly set a group. -->
-    <string name="default_permission_group">Default</string>
-    <!-- Do not translate. -->
-    <string name="permissions_format"><xliff:g id="perm_line1">%1$s</xliff:g>, <xliff:g id="perm_line2">%2$s</xliff:g></string>
     <!-- Text that is placed at the front of a permission name that is being added to an app [CHAR LIMIT=NONE] -->
     <string name="perms_new_perm_prefix"><font size="12" fgcolor="#ff900000">NEW: </font></string>
+    <!-- Text that is placed at the front of a permission name that is being added to an app [CHAR LIMIT=NONE] -->
+    <string name="perms_description_app">Provided by <xliff:g id="app_name">%1$s</xliff:g>.</string>
     <!-- Shown for an application when it doesn't require any permission grants. -->
     <string name="no_permissions">No permissions required</string>
-    <!-- When installing an application, the less-dangerous permissions are hidden.  If the user showed those, this is the text to hide them again.  -->
-    <string name="perms_hide"><b>Hide</b></string>
-    <!-- When installing an application, the less-dangerous permissions are hidden.  This is the text to show those. -->
-    <string name="perms_show_all"><b>Show all</b></string>
 
     <!-- USB storage dialog strings -->
     <!-- This is the title for the activity's window. -->
@@ -3556,4 +3560,12 @@
     <!-- STK setup Call -->
     <string name="SetupCallDefault">Accept call?</string>
 
+    <!-- Title for a button to choose the currently selected activity
+         as the default in the activity resolver. [CHAR LIMIT=25] -->
+    <string name="activity_resolver_use_always">Use Always</string>
+
+    <!-- Title for a button to choose the currently selected activity
+         from the activity resolver to use just this once. [CHAR LIMIT=25] -->
+    <string name="activity_resolver_use_once">Just Once</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 236ca6b..d79ba42 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -369,4 +369,12 @@
     <!-- Title shown in notification popup for inspecting the responsible
          application -->
     <string name="status_bar_notification_inspect_item_title">App info</string>
+
+    <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
+         mode) -->
+    <string name="notifications_off_title">Notifications off</string>
+
+    <!-- Content text for do-not-disturb mode notification -->
+    <string name="notifications_off_text">Tap here to turn notifications back on.</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 414af89..6584c7d 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -74,6 +74,7 @@
     private boolean mLongPressSent;
     private View.OnLongClickListener mLongPressListener;
     private Runnable mWatchLongPress;
+    private long mLongPressTimeout;
 
     public SwipeHelper(int swipeDirection, Callback callback, float densityScale,
             float pagingTouchSlop) {
@@ -83,6 +84,8 @@
         mVelocityTracker = VelocityTracker.obtain();
         mDensityScale = densityScale;
         mPagingTouchSlop = pagingTouchSlop;
+
+        mLongPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f); // extra long-press!
     }
 
     public void setLongPressListener(View.OnLongClickListener listener) {
@@ -180,7 +183,7 @@
         }
     }
 
-    private void removeLongPressCallback() {
+    public void removeLongPressCallback() {
         if (mWatchLongPress != null) {
             mHandler.removeCallbacks(mWatchLongPress);
         }
@@ -214,7 +217,7 @@
                                 }
                             };
                         }
-                        mHandler.postDelayed(mWatchLongPress, ViewConfiguration.getLongPressTimeout());
+                        mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
                     }
 
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7317c5c..f0db2bce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,8 @@
     protected RecentsPanelView mRecentsPanel;
     protected RecentTasksLoader mRecentTasksLoader;
 
+    protected PopupMenu mNotificationBlamePopup;
+
     // UI-specific methods
 
     /**
@@ -238,9 +240,11 @@
                 final String packageNameF = (String) v.getTag();
                 if (packageNameF == null) return false;
                 if (v.getWindowToken() == null) return false;
-                PopupMenu popup = new PopupMenu(mContext, v);
-                popup.getMenuInflater().inflate(R.menu.notification_popup_menu, popup.getMenu());
-                popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+                mNotificationBlamePopup = new PopupMenu(mContext, v);
+                mNotificationBlamePopup.getMenuInflater().inflate(
+                        R.menu.notification_popup_menu,
+                        mNotificationBlamePopup.getMenu());
+                mNotificationBlamePopup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                     public boolean onMenuItemClick(MenuItem item) {
                         if (item.getItemId() == R.id.notification_inspect_item) {
                             startApplicationDetailsActivity(packageNameF);
@@ -251,13 +255,20 @@
                         return true;
                     }
                 });
-                popup.show();
+                mNotificationBlamePopup.show();
 
                 return true;
             }
         };
     }
 
+    public void dismissPopups() {
+        if (mNotificationBlamePopup != null) {
+            mNotificationBlamePopup.dismiss();
+            mNotificationBlamePopup = null;
+        }
+    }
+
     public void dismissIntruder() {
         // pass
     }
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 3b00300..c1d3c57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1247,6 +1247,10 @@
             return;
         }
         mExpanded = false;
+
+        // Close any "App info" popups that might have snuck on-screen
+        dismissPopups();
+
         if (mPostCollapseCleanup != null) {
             mPostCollapseCleanup.run();
             mPostCollapseCleanup = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 93803d9..03dfd1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -32,6 +32,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
 
 import com.android.systemui.ExpandHelper;
@@ -108,6 +109,14 @@
         mSwipeHelper.setLongPressListener(listener);
     }
 
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (!hasWindowFocus) {
+            mSwipeHelper.removeLongPressCallback();
+        }
+    }
+
     public void setAnimateBounds(boolean anim) {
         mAnimateBounds = anim;
     }
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 6e87dd7..4ad90ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -67,6 +67,7 @@
 import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.recent.RecentsPanelView;
 import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.DoNotDisturb;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -165,6 +166,7 @@
     BluetoothController mBluetoothController;
     LocationController mLocationController;
     NetworkController mNetworkController;
+    DoNotDisturb mDoNotDisturb;
 
     ViewGroup mBarContents;
 
@@ -520,6 +522,9 @@
         // The icons
         mLocationController = new LocationController(mContext); // will post a notification
 
+        // watch the PREF_DO_NOT_DISTURB and convert to appropriate disable() calls
+        mDoNotDisturb = new DoNotDisturb(mContext);
+
         mBatteryController = new BatteryController(mContext);
         mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
         mBluetoothController = new BluetoothController(mContext);
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index a9d4b59..1a56b80 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -616,10 +616,12 @@
         // persist if beyond new thresholds
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
                 : System.currentTimeMillis();
-        mDevRecorder.maybePersistLocked(currentTime);
-        mXtRecorder.maybePersistLocked(currentTime);
-        mUidRecorder.maybePersistLocked(currentTime);
-        mUidTagRecorder.maybePersistLocked(currentTime);
+        synchronized (mStatsLock) {
+            mDevRecorder.maybePersistLocked(currentTime);
+            mXtRecorder.maybePersistLocked(currentTime);
+            mUidRecorder.maybePersistLocked(currentTime);
+            mUidTagRecorder.maybePersistLocked(currentTime);
+        }
 
         // re-arm global alert
         registerGlobalAlert();
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index c915932..27af313 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -42,8 +42,17 @@
             this.layer = layer;
             int w = r-l;
             int h = b-t;
-            surface = new Surface(session, 0, "BlackSurface",
-                    -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+                surface = new WindowStateAnimator.SurfaceTrace(session, 0, "BlackSurface("
+                        + l + ", " + t + ")",
+                        -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+            } else {
+                surface = new Surface(session, 0, "BlackSurface",
+                        -1, w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+            }
+            surface.setAlpha(1);
+            surface.setLayer(layer);
+            surface.show();
             if (WindowManagerService.SHOW_TRANSACTIONS ||
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
                             "  BLACK " + surface + ": CREATE layer=" + layer);
@@ -58,8 +67,6 @@
             surface.setMatrix(
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
-            surface.setAlpha(1.0f);
-            surface.setLayer(layer);
             if (false) {
                 Slog.i(WindowManagerService.TAG, "Black Surface @ (" + left + "," + top + "): ("
                         + mTmpFloats[Matrix.MTRANS_X] + ","
@@ -159,14 +166,6 @@
         }
     }
 
-    public void setAlpha(float alpha) {
-        for (int i=0; i<mBlackSurfaces.length; i++) {
-            if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].surface.setAlpha(alpha);
-            }
-        }
-    }
-
     public void clearMatrix() {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 13013a8..938db9e 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -862,7 +862,6 @@
             } else {
                 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
                 mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
-                mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
             }
         }