Merge "Fix GL shader bugs" into jb-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index f0148b4..a3f9be5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -62,21 +62,17 @@
     field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
     field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
     field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
-    field public static final java.lang.String INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
     field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
     field public static final java.lang.String INTERNET = "android.permission.INTERNET";
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
     field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
     field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
-    field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
     field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
     field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
     field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
-    field public static final java.lang.String NET_TUNNELING = "android.permission.NET_TUNNELING";
     field public static final java.lang.String NFC = "android.permission.NFC";
-    field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
     field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
     field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
     field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
@@ -3901,11 +3897,12 @@
     method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int);
     method public static android.app.PendingIntent getActivity(android.content.Context, int, android.content.Intent, int, android.os.Bundle);
     method public static android.app.PendingIntent getBroadcast(android.content.Context, int, android.content.Intent, int);
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
     method public android.content.IntentSender getIntentSender();
     method public static android.app.PendingIntent getService(android.content.Context, int, android.content.Intent, int);
-    method public java.lang.String getTargetPackage();
-    method public int getTargetUid();
-    method public android.os.UserHandle getTargetUserHandle();
+    method public deprecated java.lang.String getTargetPackage();
     method public static android.app.PendingIntent readPendingIntentOrNullFromParcel(android.os.Parcel);
     method public void send() throws android.app.PendingIntent.CanceledException;
     method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -6060,9 +6057,10 @@
 
   public class IntentSender implements android.os.Parcelable {
     method public int describeContents();
-    method public java.lang.String getTargetPackage();
-    method public int getTargetUid();
-    method public android.os.UserHandle getTargetUserHandle();
+    method public java.lang.String getCreatorPackage();
+    method public int getCreatorUid();
+    method public android.os.UserHandle getCreatorUserHandle();
+    method public deprecated java.lang.String getTargetPackage();
     method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
     method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
@@ -6705,17 +6703,6 @@
     field public java.lang.String packageName;
   }
 
-  public class PackageUserState {
-    ctor public PackageUserState();
-    ctor public PackageUserState(android.content.pm.PackageUserState);
-    field public java.util.HashSet disabledComponents;
-    field public int enabled;
-    field public java.util.HashSet enabledComponents;
-    field public boolean installed;
-    field public boolean notLaunched;
-    field public boolean stopped;
-  }
-
   public class PathPermission extends android.os.PatternMatcher {
     ctor public PathPermission(java.lang.String, int, java.lang.String, java.lang.String);
     ctor public PathPermission(android.os.Parcel);
@@ -13037,6 +13024,11 @@
     field public static final int SSL_UNTRUSTED = 3; // 0x3
   }
 
+  public class X509TrustManagerExtensions {
+    ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
+    method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException;
+  }
+
 }
 
 package android.net.nsd {
@@ -16594,7 +16586,6 @@
 
   public class UserManager {
     method public java.lang.String getUserName();
-    method public boolean supportsMultipleUsers();
   }
 
   public abstract class Vibrator {
@@ -20016,6 +20007,8 @@
 
   public class Script extends android.renderscript.BaseObj {
     method public void bindAllocation(android.renderscript.Allocation, int);
+    method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element);
+    method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
     method protected void invoke(int);
     method protected void invoke(int, android.renderscript.FieldPacker);
@@ -20045,17 +20038,39 @@
     field protected android.renderscript.Element mElement;
   }
 
+  public static final class Script.FieldID extends android.renderscript.BaseObj {
+  }
+
+  public static final class Script.KernelID extends android.renderscript.BaseObj {
+  }
+
   public class ScriptC extends android.renderscript.Script {
     ctor protected ScriptC(int, android.renderscript.RenderScript);
     ctor protected ScriptC(android.renderscript.RenderScript, android.content.res.Resources, int);
   }
 
+  public final class ScriptGroup extends android.renderscript.BaseObj {
+    method public void execute();
+    method public void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+    method public void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation);
+  }
+
+  public static final class ScriptGroup.Builder {
+    ctor public ScriptGroup.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID);
+    method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup.Builder addKernel(android.renderscript.Script.KernelID);
+    method public android.renderscript.ScriptGroup create();
+  }
+
   public abstract class ScriptIntrinsic extends android.renderscript.Script {
   }
 
   public final class ScriptIntrinsicBlur extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicBlur create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
     method public void setInput(android.renderscript.Allocation);
     method public void setRadius(float);
   }
@@ -20063,6 +20078,7 @@
   public final class ScriptIntrinsicColorMatrix extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicColorMatrix create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
     method public void setColorMatrix(android.renderscript.Matrix4f);
     method public void setColorMatrix(android.renderscript.Matrix3f);
     method public void setGreyscale();
@@ -20073,6 +20089,8 @@
   public final class ScriptIntrinsicConvolve3x3 extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicConvolve3x3 create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
     method public void setCoefficients(float[]);
     method public void setInput(android.renderscript.Allocation);
   }
@@ -20080,6 +20098,8 @@
   public final class ScriptIntrinsicConvolve5x5 extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicConvolve5x5 create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID();
     method public void setCoefficients(float[]);
     method public void setInput(android.renderscript.Allocation);
   }
@@ -20087,6 +20107,7 @@
   public final class ScriptIntrinsicLUT extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicLUT create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation, android.renderscript.Allocation);
+    method public android.renderscript.Script.KernelID getKernelID();
     method public void setAlpha(int, int);
     method public void setBlue(int, int);
     method public void setGreen(int, int);
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index a3c1838..e7cea57 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -32,8 +32,8 @@
 
 /**
  * A description of an Intent and target action to perform with it.  Instances
- * of this class are created with {@link #getActivity},
- * {@link #getBroadcast}, {@link #getService}; the returned object can be
+ * of this class are created with {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, and {@link #getService}; the returned object can be
  * handed to other applications so that they can perform the action you
  * described on your behalf at a later time.
  *
@@ -54,6 +54,34 @@
  * categories, and components, and same flags), it will receive a PendingIntent
  * representing the same token if that is still valid, and can thus call
  * {@link #cancel} to remove it.
+ *
+ * <p>Because of this behavior, it is important to know when two Intents
+ * are considered to be the same for purposes of retrieving a PendingIntent.
+ * A common mistake people make is to create multiple PendingIntent objects
+ * with Intents that only vary in their "extra" contents, expecting to get
+ * a different PendingIntent each time.  This does <em>not</em> happen.  The
+ * parts of the Intent that are used for matching are the same ones defined
+ * by {@link Intent#filterEquals(Intent) Intent.filterEquals}.  If you use two
+ * Intent objects that are equivalent as per
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
+ * the same PendingIntent for both of them.
+ *
+ * <p>There are two typical ways to deal with this.
+ *
+ * <p>If you truly need multiple distinct PendingIntent objects active at
+ * the same time (such as to use as two notifications that are both shown
+ * at the same time), then you will need to ensure there is something that
+ * is different about them to associate them with different PendingIntents.
+ * This may be any of the Intent attributes considered by
+ * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
+ * request code integers supplied to {@link #getActivity}, {@link #getActivities},
+ * {@link #getBroadcast}, or {@link #getService}.
+ *
+ * <p>If you only need one PendingIntent active at a time for any of the
+ * Intents you will use, then you can alternatively use the flags
+ * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
+ * cancel or modify whatever current PendingIntent is associated with the
+ * Intent you are supplying.
  */
 public final class PendingIntent implements Parcelable {
     private final IIntentSender mTarget;
@@ -622,6 +650,20 @@
     }
 
     /**
+     * @deprecated Renamed to {@link #getCreatorPackage()}.
+     */
+    @Deprecated
+    public String getTargetPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getPackageForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Return the package name of the application that created this
      * PendingIntent, that is the identity under which you will actually be
      * sending the Intent.  The returned string is supplied by the system, so
@@ -630,7 +672,7 @@
      * @return The package name of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public String getTargetPackage() {
+    public String getCreatorPackage() {
         try {
             return ActivityManagerNative.getDefault()
                 .getPackageForIntentSender(mTarget);
@@ -649,7 +691,7 @@
      * @return The uid of the PendingIntent, or -1 if there is
      * none associated with it.
      */
-    public int getTargetUid() {
+    public int getCreatorUid() {
         try {
             return ActivityManagerNative.getDefault()
                 .getUidForIntentSender(mTarget);
@@ -670,7 +712,7 @@
      * @return The user handle of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public UserHandle getTargetUserHandle() {
+    public UserHandle getCreatorUserHandle() {
         try {
             int uid = ActivityManagerNative.getDefault()
                 .getUidForIntentSender(mTarget);
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 51a81c5..84a447f 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -117,7 +117,7 @@
     private OnClickHandler mOnClickHandler;
 
     public AppWidgetHost(Context context, int hostId) {
-        this(context, hostId, null, Looper.getMainLooper());
+        this(context, hostId, null, context.getMainLooper());
     }
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7438ba8..161670f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -856,8 +856,10 @@
     public abstract void startActivity(Intent intent);
 
     /**
-     * Same as {@link #startActivity(Intent)}, but for a specific user. It requires holding
-     * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+     * Version of {@link #startActivity(Intent)} that allows you to specify the
+     * user the activity will be started for.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS_FULL permission.
      * @param intent The description of the activity to start.
      * @param user The UserHandle of the user to start this activity for.
      * @throws ActivityNotFoundException
@@ -895,8 +897,10 @@
     public abstract void startActivity(Intent intent, Bundle options);
 
     /**
-     * Same as {@link #startActivity(Intent, Bundle)}, but for a specific user. It requires holding
-     * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+     * Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
+     * user the activity will be started for.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS_FULL permission.
      * @param intent The description of the activity to start.
      * @param options Additional options for how the Activity should be started.
      * May be null if there are no options.  See {@link android.app.ActivityOptions}
@@ -1118,10 +1122,10 @@
             Bundle initialExtras);
 
     /**
-     * Same as {@link #sendBroadcast(Intent)}, but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of {@link #sendBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      * @param intent The intent to broadcast
      * @param user UserHandle to send the intent to.
      * @see #sendBroadcast(Intent)
@@ -1129,10 +1133,10 @@
     public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
 
     /**
-     * Same as {@link #sendBroadcast(Intent, String)}, but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -1147,12 +1151,12 @@
             String receiverPermission);
 
     /**
-     * Same as
-     * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)},
-     * but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of
+     * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
+     * that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -1261,11 +1265,10 @@
     public abstract void removeStickyBroadcast(Intent intent);
 
     /**
-     * Same as {@link #sendStickyBroadcast(Intent)},
-     * but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      * Intent will receive the broadcast, and the Intent will be held to
@@ -1277,12 +1280,12 @@
     public abstract void sendStickyBroadcastAsUser(Intent intent, UserHandle user);
 
     /**
-     * Same as
-     * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
-     * but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of
+     * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
+     * that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -1309,12 +1312,10 @@
             Bundle initialExtras);
 
     /**
-     * Same as
-     * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
-     * but for a specific user.  This broadcast
-     * can only be sent to receivers that are part of the calling application.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
-     * permission.
+     * Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
+     * user the broadcast will be sent to.  This is not available to applications
+     * that are not pre-installed on the system image.  Using it requires holding
+     * the INTERACT_ACROSS_USERS permission.
      *
      * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
      * permission in order to use this API.  If you do not hold that
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d3b8648..e8507bc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2376,6 +2376,16 @@
     public static final String ACTION_USER_SWITCHED =
             "android.intent.action.USER_SWITCHED";
 
+    /**
+     * Broadcast sent to the system when a user's information changes. Carries an extra
+     * {@link #EXTRA_USER_HANDLE} to indicate which user's information changed.
+     * This is only sent to registered receivers, not manifest receivers. It is sent to the user
+     * whose information has changed.
+     * @hide
+     */
+    public static final String ACTION_USER_INFO_CHANGED =
+            "android.intent.action.USER_INFO_CHANGED";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 6c3cf99..166495b 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -205,6 +205,20 @@
     }
 
     /**
+     * @deprecated Renamed to {@link #getCreatorPackage()}.
+     */
+    @Deprecated
+    public String getTargetPackage() {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getPackageForIntentSender(mTarget);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Return the package name of the application that created this
      * IntentSender, that is the identity under which you will actually be
      * sending the Intent.  The returned string is supplied by the system, so
@@ -213,7 +227,7 @@
      * @return The package name of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public String getTargetPackage() {
+    public String getCreatorPackage() {
         try {
             return ActivityManagerNative.getDefault()
                 .getPackageForIntentSender(mTarget);
@@ -232,7 +246,7 @@
      * @return The uid of the PendingIntent, or -1 if there is
      * none associated with it.
      */
-    public int getTargetUid() {
+    public int getCreatorUid() {
         try {
             return ActivityManagerNative.getDefault()
                 .getUidForIntentSender(mTarget);
@@ -253,7 +267,7 @@
      * @return The user handle of the PendingIntent, or null if there is
      * none associated with it.
      */
-    public UserHandle getTargetUserHandle() {
+    public UserHandle getCreatorUserHandle() {
         try {
             int uid = ActivityManagerNative.getDefault()
                 .getUidForIntentSender(mTarget);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4784d7f..fd488ae 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2434,8 +2434,7 @@
      * @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW}
      *            or {@link PackageManager#VERIFICATION_REJECT}.
      * @throws SecurityException if the caller does not have the
-     *            {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
-     *            permission.
+     *            PACKAGE_VERIFICATION_AGENT permission.
      */
     public abstract void verifyPendingInstall(int id, int verificationCode);
 
@@ -2469,8 +2468,7 @@
      *            bounds value; namely, 0 or
      *            {@link PackageManager#MAXIMUM_VERIFICATION_TIMEOUT}.
      * @throws SecurityException if the caller does not have the
-     *            {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
-     *            permission.
+     *            PACKAGE_VERIFICATION_AGENT permission.
      */
     public abstract void extendVerificationTimeout(int id,
             int verificationCodeAtTimeout, long millisecondsToDelay);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 1a71bfb..3579977 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -22,6 +22,7 @@
 
 /**
  * Per-user state information about a package.
+ * @hide
  */
 public class PackageUserState {
     public boolean stopped;
diff --git a/core/java/android/net/X509TrustManagerExtensions.java b/core/java/android/net/X509TrustManagerExtensions.java
new file mode 100644
index 0000000..115e972
--- /dev/null
+++ b/core/java/android/net/X509TrustManagerExtensions.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package android.net.http;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.KeyManagementException;
+import java.util.List;
+
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
+
+/**
+ * X509TrustManager wrapper exposing Android-added features.
+ *
+ * <p> The checkServerTrusted method allows callers to perform additional
+ * verification of certificate chains after they have been successfully
+ * verified by the platform.</p>
+ */
+public class X509TrustManagerExtensions {
+
+    TrustManagerImpl mDelegate;
+
+    /**
+     * Constructs a new X509TrustManagerExtensions wrapper.
+     *
+     * @param tm A {@link X509TrustManager} as returned by TrustManagerFactory.getInstance();
+     * @throws IllegalArgumentException If tm is an unsupported TrustManager type.
+     */
+    public X509TrustManagerExtensions(X509TrustManager tm) throws IllegalArgumentException {
+        if (tm instanceof TrustManagerImpl) {
+            mDelegate = (TrustManagerImpl) tm;
+        } else {
+            throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+        }
+    }
+
+    /**
+     * Verifies the given certificate chain.
+     *
+     * <p>See {@link X509TrustManager#checkServerTrusted(X509Certificate[], String)} for a
+     * description of the chain and authType parameters. The final parameter, host, should be the
+     * hostname of the server.</p>
+     *
+     * @throws CertificateException if the chain does not verify correctly.
+     * @return the properly ordered chain used for verification as a list of X509Certificates.
+     */
+    public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,
+                                                    String host) throws CertificateException {
+        return mDelegate.checkServerTrusted(chain, authType, host);
+    }
+}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 653c5f3..0798913 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -19,6 +19,7 @@
 
 import android.os.ParcelFileDescriptor;
 import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
 
 /**
  *  {@hide}
@@ -27,8 +28,8 @@
     UserInfo createUser(in String name, int flags);
     boolean removeUser(int userHandle);
     void setUserName(int userHandle, String name);
-    ParcelFileDescriptor setUserIcon(int userHandle);
-    ParcelFileDescriptor getUserIcon(int userHandle);
+    void setUserIcon(int userHandle, in Bitmap icon);
+    Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers();
     UserInfo getUserInfo(int userHandle);
     void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cac1e07..392aff7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -18,6 +18,7 @@
 import com.android.internal.R;
 import android.content.Context;
 import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
 import android.util.Log;
 
 import java.util.List;
@@ -40,6 +41,7 @@
     /**
      * Returns whether the system supports multiple users.
      * @return true if multiple users can be created, false if it is a single user device.
+     * @hide
      */
     public boolean supportsMultipleUsers() {
         return getMaxSupportedUsers() > 1;
@@ -55,8 +57,9 @@
     }
 
     /**
-     * Returns the user name of the user making this call.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Returns the user name of the user making this call.  This call is only
+     * available to applications on the system image; it requires the
+     * MANAGE_USERS permission.
      * @return the user name
      */
     public String getUserName() {
@@ -151,32 +154,30 @@
     }
 
     /**
-     * Returns a file descriptor for the user's photo. PNG data can be written into this file.
+     * Sets the user's photo.
      * @param userHandle the user for whom to change the photo.
-     * @return a {@link ParcelFileDescriptor} to which to write the photo.
+     * @param icon the bitmap to set as the photo.
      * @hide
      */
-    public ParcelFileDescriptor setUserIcon(int userHandle) {
+    public void setUserIcon(int userHandle, Bitmap icon) {
         try {
-            return mService.setUserIcon(userHandle);
+            mService.setUserIcon(userHandle, icon);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not set the user icon ", re);
-            return null;
         }
     }
 
     /**
      * Returns a file descriptor for the user's photo. PNG data can be read from this file.
      * @param userHandle the user whose photo we want to read.
-     * @return a {@link ParcelFileDescriptor} from which to read the file, or null if there's no
-     * photo.
+     * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
      * @hide
      */
-    public ParcelFileDescriptor getUserIcon(int userHandle) {
+    public Bitmap getUserIcon(int userHandle) {
         try {
             return mService.getUserIcon(userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set the user icon ", re);
+            Log.w(TAG, "Could not get the user icon ", re);
             return null;
         }
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a182234..68ce72f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5614,6 +5614,13 @@
                "wifi_supplicant_scan_interval_ms";
 
        /**
+        * The interval in milliseconds to scan at supplicant when p2p is connected
+        * @hide
+        */
+       public static final String WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS =
+               "wifi_scan_interval_p2p_connected_ms";
+
+       /**
         * Whether the Wi-Fi watchdog is enabled.
         */
        public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index f906e24..446a51e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -733,13 +733,17 @@
          */
         void checkEglErrors() {
             if (isEnabled()) {
-                int error = sEgl.eglGetError();
-                if (error != EGL_SUCCESS) {
-                    // something bad has happened revert to
-                    // normal rendering.
-                    Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
-                    fallback(error != EGL11.EGL_CONTEXT_LOST);
-                }
+                checkEglErrorsForced();
+            }
+        }
+
+        private void checkEglErrorsForced() {
+            int error = sEgl.eglGetError();
+            if (error != EGL_SUCCESS) {
+                // something bad has happened revert to
+                // normal rendering.
+                Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
+                fallback(error != EGL11.EGL_CONTEXT_LOST);
             }
         }
 
@@ -812,7 +816,9 @@
                         throw new RuntimeException("eglInitialize failed " +
                                 GLUtils.getEGLErrorString(sEgl.eglGetError()));
                     }
-        
+
+                    checkEglErrorsForced();
+
                     sEglConfig = chooseEglConfig();
                     if (sEglConfig == null) {
                         // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index c93da06..d6f63a7 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -832,7 +832,6 @@
             sConfirmSafeVolumeDialog.dismiss();
         }
         sConfirmSafeVolumeDialog = new AlertDialog.Builder(mContext)
-                .setTitle(android.R.string.dialog_alert_title)
                 .setMessage(com.android.internal.R.string.safe_media_volume_warning)
                 .setPositiveButton(com.android.internal.R.string.yes,
                                     new DialogInterface.OnClickListener() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index dc4ee3a..34ade74 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -400,6 +400,7 @@
         int nonOverflowCount = 0;
         int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
         boolean hasOverflow = false;
+        final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < childCount; i++) {
             final View v = getChildAt(i);
             if (v.getVisibility() == GONE) {
@@ -414,8 +415,15 @@
                 }
 
                 int height = v.getMeasuredHeight();
-                int r = getWidth() - getPaddingRight() - p.rightMargin;
-                int l = r - overflowWidth;
+                int r;
+                int l;
+                if (isLayoutRtl) {
+                    l = getPaddingLeft() + p.leftMargin;
+                    r = l + overflowWidth;
+                } else {
+                    r = getWidth() - getPaddingRight() - p.rightMargin;
+                    l = r - overflowWidth;
+                }
                 int t = midVertical - (height / 2);
                 int b = t + height;
                 v.layout(l, t, r, b);
@@ -448,20 +456,38 @@
         final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
         final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
 
-        int startLeft = getPaddingLeft();
-        for (int i = 0; i < childCount; i++) {
-            final View v = getChildAt(i);
-            final LayoutParams lp = (LayoutParams) v.getLayoutParams();
-            if (v.getVisibility() == GONE || lp.isOverflowButton) {
-                continue;
-            }
+        if (isLayoutRtl) {
+            int startRight = getWidth() - getPaddingRight();
+            for (int i = 0; i < childCount; i++) {
+                final View v = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+                if (v.getVisibility() == GONE || lp.isOverflowButton) {
+                    continue;
+                }
 
-            startLeft += lp.leftMargin;
-            int width = v.getMeasuredWidth();
-            int height = v.getMeasuredHeight();
-            int t = midVertical - height / 2;
-            v.layout(startLeft, t, startLeft + width, t + height);
-            startLeft += width + lp.rightMargin + spacerSize;
+                startRight -= lp.rightMargin;
+                int width = v.getMeasuredWidth();
+                int height = v.getMeasuredHeight();
+                int t = midVertical - height / 2;
+                v.layout(startRight - width, t, startRight, t + height);
+                startRight -= width + lp.leftMargin + spacerSize;
+            }
+        } else {
+            int startLeft = getPaddingLeft();
+            for (int i = 0; i < childCount; i++) {
+                final View v = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
+                if (v.getVisibility() == GONE || lp.isOverflowButton) {
+                    continue;
+                }
+
+                startLeft += lp.leftMargin;
+                int width = v.getMeasuredWidth();
+                int height = v.getMeasuredHeight();
+                int t = midVertical - height / 2;
+                v.layout(startLeft, t, startLeft + width, t + height);
+                startLeft += width + lp.rightMargin + spacerSize;
+            }
         }
     }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 90e85e6..fc04cd1 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -650,8 +650,7 @@
 
 static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj) {
     ScopedUtfChars name(env, nameObj);
-    // TODO: pass the name to SF.
-    sp<IBinder> token(SurfaceComposerClient::createDisplay());
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str())));
     return javaObjectForIBinder(env, token);
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0bc09aa..89d78b6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -981,7 +981,7 @@
         android:protectionLevel="dangerous"
         android:label="@string/permlab_getTasks"
         android:description="@string/permdesc_getTasks" />
-    <!-- Allows an application to call APIs that allow it to do interactions
+    <!-- @hide Allows an application to call APIs that allow it to do interactions
          across the users on the device, using singleton services and
          user-targeted broadcasts.  This permission is not available to
          third party applications. -->
@@ -1000,7 +1000,7 @@
         android:label="@string/permlab_interactAcrossUsersFull"
         android:description="@string/permdesc_interactAcrossUsersFull" />
 
-    <!-- Allows an application to call APIs that allow it to query and manage
+    <!-- @hide Allows an application to call APIs that allow it to query and manage
          users on the device. This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.MANAGE_USERS"
@@ -1769,7 +1769,7 @@
         android:description="@string/permdesc_devicePower"
         android:protectionLevel="signature" />
 
-   <!-- Allows low-level access to tun tap driver -->
+   <!-- @hide Allows low-level access to tun tap driver -->
     <permission android:name="android.permission.NET_TUNNELING"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="signature" />
@@ -1981,7 +1981,7 @@
           android:protectionLevel="signature" />
     <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
 
-    <!-- Package verifier needs to have this permission before the PackageManager will
+    <!-- @hide Package verifier needs to have this permission before the PackageManager will
          trust it to verify packages.
     -->
     <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 1486d9c..afb9485 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -37,5 +37,8 @@
          used for picking activities to handle an intent. -->
     <integer name="config_maxResolverActivityColumns">3</integer>
 
+    <!-- Use a larger scaling span for larger screen devices. -->
+    <dimen name="config_minScalingSpan">30mm</dimen>
+
 </resources>
 
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3c0c0a7..7209e4e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -299,8 +299,9 @@
          with this component (by binding to a service for example) those processes will
          always interact with the instance running for user 0.  Enabling
          single user mode forces "exported" of the component to be false, to
-         help avoid introducing multi-user security bugs.  You must hold the
-         permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS} in order
+         help avoid introducing multi-user security bugs.  This feature is only
+         available to applications built in to the system image; you must hold the
+         permission INTERACT_ACROSS_USERS in order
          to use this feature.  This flag can only be used with services,
          receivers, and providers; it can not be used with activities. -->
     <attr name="singleUser" format="boolean" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1a9a0a9..297e72a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -292,6 +292,9 @@
     <!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
 
+    <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
+    <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
+
     <!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario
          where the chipset does not support background scanning (config_wifi_background_scan_suport
          is false) to set up a periodic wake up scan so that the device can connect to a new access
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 56e5ce1..b904c60 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3890,7 +3890,7 @@
     <!-- Message shown in dialog when user is attempting to set the music volume above the
     recommended maximum level for headphones -->
     <string name="safe_media_volume_warning" product="default">
-       "Raise volume above the recommended level?"
+       "Raise volume above safe level?\nListening at high volume for long periods may damage your hearing."
     </string>
 
     <string name="kg_temp_back_string"> &lt; </string> <!-- TODO: remove this -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eb56d08..0360224 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -275,6 +275,7 @@
   <java-symbol type="integer" name="config_ntpTimeout" />
   <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
+  <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
   <java-symbol type="integer" name="db_connection_pool_size" />
   <java-symbol type="integer" name="db_journal_size_limit" />
   <java-symbol type="integer" name="db_wal_autocheckpoint" />
diff --git a/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
new file mode 100644
index 0000000..b2e1895
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package android.net.http;
+
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.X509TrustManager;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
+
+public class X509TrustManagerExtensionsTest extends TestCase {
+
+    private class NotATrustManagerImpl implements X509TrustManager {
+
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {}
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {}
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return new X509Certificate[0];
+        }
+    }
+
+    public void testBadCast() throws Exception {
+        NotATrustManagerImpl ntmi = new NotATrustManagerImpl();
+        try {
+            X509TrustManagerExtensions tme = new X509TrustManagerExtensions(ntmi);
+        } catch (IllegalArgumentException ignored) {
+            return;
+        }
+        fail();
+    }
+
+    public void testGoodCast() throws Exception {
+        String defaultType = KeyStore.getDefaultType();
+        TrustManagerImpl tmi = new TrustManagerImpl(KeyStore.getInstance(defaultType));
+        X509TrustManagerExtensions tme = new X509TrustManagerExtensions(tmi);
+    }
+}
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index 31274c5..3ba3f71 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -109,9 +109,7 @@
 
 </p>
 <p>
-
-<a href="{@docRoot}downloads/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
-
+<a href="{@docRoot}downloads/design/Android_Design_Icons_20120814.zip">Download the Action Bar Icon Pack</a>
 </p>
 
 <div class="layout-content-row">
diff --git a/docs/html/distribute/distribute_toc.cs b/docs/html/distribute/distribute_toc.cs
index f11e965..76073fb 100644
--- a/docs/html/distribute/distribute_toc.cs
+++ b/docs/html/distribute/distribute_toc.cs
@@ -72,10 +72,10 @@
         <span class="en">Linking to Your Products</a></li>
        <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/badges.html">
         <span class="en">Google Play Badges</a></li>
-       <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/brand.html">
-        <span class="en">Brand Assets and Guidelines</a></li>
        <li><a href="<?cs var:toroot ?>distribute/promote/device-art.html">
         <span class="en">Device Art Generator</a></li>
+       <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/brand.html">
+        <span class="en">Brand Assets and Guidelines</a></li>
      </ul>
    </li>
 
diff --git a/docs/html/distribute/googleplay/promote/badges.jd b/docs/html/distribute/googleplay/promote/badges.jd
index de12e2a..7b64be3 100644
--- a/docs/html/distribute/googleplay/promote/badges.jd
+++ b/docs/html/distribute/googleplay/promote/badges.jd
@@ -1,11 +1,20 @@
 page.title=Google Play Badges
 @jd:body
 
-<p>Google Play badges give you an officially branded way of promoting your app to Android users. Use the form below to quickly create badges to link users to your products from web pages, ads, reviews, and more. See <a href="linking.html">Linking to your products</a> for more ways to bring users to your apps.</p>
+<p>Google Play badges allow you to promote your app with official branding in your
+online ads, promotional materials, or anywhere else you want a link to your app.</p>
 
-<p>Input your app's package or your publisher name, choose the style, size, and language, and click "Build my badge". The form will generate code for an embbeded button that links to your app's product page or a list of your apps. </p>
+<p>In the form below,
+input your app's package name or publisher name, choose the badge style,
+click <em>Build my badge</em>, then paste the HTML into your web content.</p>
 
-<p>Note that you should not modify the Google Play badges after generating them, including colors, size, text, and logo. See <a href="http://www.android.com/branding.html">Android Brand Guidelines</a> for more information.</p>
+<p>If you're creating a promotional web page for your app, you should also use the
+<a href="{@docRoot}distribute/promote/device-art.html">Device Art Generator</a>, which quickly
+wraps your screenshots in real device artwork.</p>
+
+<p>For guidelines when using the Google Play badge and other brand assets,
+see the <a href="{@docRoot}distribute/googleplay/promote/brand.html">Brand Assets and
+Guidelines</a>.</p>
 
 <style type="text/css">
 
@@ -34,11 +43,13 @@
 }
 
 div.button-row input {
-  vertical-align:120%;
+  vertical-align:middle;
+  margin:0 5px 0 0;
 }
 
 #jd-content div.button-row img {
   margin: 0;
+  vertical-align:middle;
 }
 
 </style>
@@ -46,7 +57,7 @@
 <script type="text/javascript">
 
 // variables for creating 'try it out' demo button
-var imagePath = "http://www.android.com/images/brand/"
+var imagePath = "http://developer.android.com/images/brand/"
 var linkStart = "<a href=\"http://play.google.com/store/";
 var imageStart = "\">\n"
         + "  <img alt=\"";
@@ -167,28 +178,29 @@
             onclick="return clearLabel('publisher','Example, Inc.');">clear</a>
          <br/><br/>
 
-<div class="button-row">
-  <input type="radio" name="buttonStyle" value="get_it_on_play_logo_small" id="ns" checked="checked" />
-    <label for="ns"><img src="http://www.android.com/images/brand/get_it_on_play_logo_small.png"
-alt="Get it on Google Play (small)" /></label>
-    &nbsp;&nbsp;&nbsp;&nbsp;
-  <input type="radio" name="buttonStyle" value="get_it_on_play_logo_large" id="nm" />
-    <label for="nm"><img src="http://www.android.com/images/brand/get_it_on_play_logo_large.png"
-alt="Get it on Google Play (large)" /></label>
-</div>
 
 <div class="button-row">
-  <input type="radio" name="buttonStyle" value="android_app_on_play_logo_small" id="ws" />
-    <label for="ws"><img src="http://www.android.com/images/brand/android_app_on_play_logo_small.png"
+  <input type="radio" name="buttonStyle" value="en_app_rgb_wo_45" id="ws" checked="checked" />
+    <label for="ws"><img src="{@docRoot}images/brand/en_app_rgb_wo_45.png"
 alt="Android app on Google Play (small)" /></label>
     &nbsp;&nbsp;&nbsp;&nbsp;
-  <input type="radio" name="buttonStyle" value="android_app_on_play_logo_large" id="wm" />
-    <label for="wm"><img src="http://www.android.com/images/brand/android_app_on_play_logo_large.png"
+  <input type="radio" name="buttonStyle" value="en_app_rgb_wo_60" id="wm" />
+    <label for="wm"><img src="{@docRoot}images/brand/en_app_rgb_wo_60.png"
 alt="Android app on Google Play (large)" /></label>
 </div>
 
+<div class="button-row">
+  <input type="radio" name="buttonStyle" value="en_generic_rgb_wo_45" id="ns" />
+    <label for="ns"><img src="{@docRoot}images/brand/en_generic_rgb_wo_45.png"
+alt="Get it on Google Play (small)" /></label>
+    &nbsp;&nbsp;&nbsp;&nbsp;
+  <input type="radio" name="buttonStyle" value="en_generic_rgb_wo_60" id="nm" />
+    <label for="nm"><img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png"
+alt="Get it on Google Play (large)" /></label>
+</div>
+
   <input type="button" onclick="return buildButton(this.parentNode)" value="Build my badge"
-style="padding:5px" />
+style="padding:10px" />
   <br/>
 </form>
 
diff --git a/docs/html/distribute/googleplay/promote/brand.jd b/docs/html/distribute/googleplay/promote/brand.jd
index 76ed619..4051553 100644
--- a/docs/html/distribute/googleplay/promote/brand.jd
+++ b/docs/html/distribute/googleplay/promote/brand.jd
@@ -88,28 +88,28 @@
           "Android is a trademark of Google Inc."</span>
         </p>
 
+
 <h2 id="brand-google_play">Google Play Brand</h2>
 
-<div style="clear:both">
-  <div style="float:right;width:50%;padding:1.5em;">
-    <p>
-      <img alt="Google Play logo" src="http://www.android.com/images/brand/google_play_logo_450.png">
-    </p>
-    <p>
-    <img alt="Get it on Google Play badge, large" src=
-            "http://www.android.com/images/brand/get_it_on_play_logo_large.png"><br>
-            Download: <a href="http://www.android.com/images/brand/get_it_on_play_logo_small.png">Small</a> | <a href=
-            "http://www.android.com/images/brand/get_it_on_play_logo_large.png">Large</a>
-          </p>
-          <p>
-            <img alt="Android App on Google Play badge, large" src=
-            "http://www.android.com/images/brand/android_app_on_play_logo_large.png"><br>
-            Download: <a href="http://www.android.com/images/brand/android_app_on_play_logo_small.png">Small</a> |
-            <a href="http://www.android.com/images/brand/android_app_on_play_large.png">Large</a>
-          </p>
-  </div> 
+    <img alt="" src="http://www.android.com/images/brand/google_play_logo_450.png"
+         style="float:right;">
+      
+    <img alt="Android app on Google Play badge, large"
+         src="{@docRoot}images/brand/en_app_rgb_wo_60.png"
+         style="float:right;clear:right;">
+
+    <img alt="Android app on Google Play badge, small"
+         src="{@docRoot}images/brand/en_app_rgb_wo_45.png"
+         style="float:right;margin:0 30px 30px">
+
+    <img alt="Get it on Google Play badge, large"
+         src="{@docRoot}images/brand/en_generic_rgb_wo_60.png"
+         style="float:right;clear:right;">
+
+    <img alt="Get it on Google Play badge, small"
+         src="{@docRoot}images/brand/en_generic_rgb_wo_45.png"
+         style="float:right;margin:0 30px 30px;">
         
-  <div style="width:45%;">
     <h4>06/ <em>Get it on Google Play</em> Badge
           </h4>
           <p>
@@ -118,57 +118,34 @@
             Play.
           </p>
           <p>
-            The logos are available in two sizes:
-          </p>
-          <ul>
-            <li>Large: 60(h) x 172(w)</li>
-            </li>
-            <li>Small 45(h) x 129(w)
-            </li>
-          </ul>
-          <p>
             Guidelines for usage:
           </p>
           <ul>
-            <li>Never separate the phrase “Get it on Google Play” or "Android App on Google Play"
-            from the Google Play logo, and do not change the color, proportions, spacing or any
-            other aspect of the logo.
+            <li>Do not modify the color, proportions, spacing or any other aspect of the badge image.
             </li>
-     </ul>
-     </div>
-     
-     <ul>
-            <li>When used online, the badge logo should be used to direct users to:
+            <li>When used alongside logos for other application marketplaces, the Google Play logo
+            should be of equal or greater size.</li>
+            <li>When used online, the badge should link to either:
               <ul>
-                <li>The Google Play landing page: <br />
-                  <span style="margin-left:1em;">http://play.google.com</span>
-                </li>
-                <li>The Google Play Apps landing page: <br />
-                 <span style="margin-left:1em;">http://play.google.com/store/apps</span>
-                </li>
-                <li>A list of products that include your company name, for example, <br />
-                <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>yourCompanyName</em></span>
-                </li>
-                <li>A list of products published by you, for example,<br />
+                <li>A list of products published by you, for example:<br />
                 <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
                 </li>
-                <li>A specific app product details page within Google Play, for example,<br />
+                <li>A specific app product details page within Google Play, for example:<br />
                 <span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
                 </li>
               </ul>
             </li>
-            <li>When used alongside logos for other application marketplaces, the Google Play logo
-            should be of equal or greater size</li>
   </ul>
-            
-            <p>For details on all the ways that you can link to your product details page in Google Play, 
-            see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
 
-          <p>For convenience, if you are using the logos online, you can use the 
-            <a href="{@docRoot}distribute/googleplay/promote/badges.html">badge generator</a>
-            to create the appropriate markup and link to your apps.</p>
+          <p>For your convenience, you can use the 
+            <a href="{@docRoot}distribute/googleplay/promote/badges.html">Googe Play badge generator</a>
+            to create badges that link to your apps on Google Play.</p>
+            
+          <p>For details on all the ways that you can link to your product details page in Google Play, 
+            see <a href="{@docRoot}distribute/googleplay/promote/linking.html">Linking to your products</a></p>
 
 <h2>Other Brands</h2>
 
 <p>Any other brands or icons depicted on this site are <em>not</em> are the property of their
 respective owners and usage is reserved. You must seek the developer for appropriate permission to use them.</p>
+
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index 52ee0d9..a6e07c8 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -57,9 +57,7 @@
 <p>We appreciate researchers practicing responsible disclosure by emailing us
 with a detailed summary of the issue and keeping the issue confidential while
 users are at risk. In return, we will make sure to keep the researcher informed
-of our progress in issuing a fix and will properly credit the reporter(s) when
-we provide the patch. We will always move swiftly to mitigate or fix an
-externally-reported flaw and provide updates to users. </p>
+of our progress in issuing a fix. </p>
 
 
 <a name="informed" id="informed"></a><h2>How can I stay informed about Android security?</h2>
diff --git a/docs/html/images/brand/en_app_rgb_wo_45.png b/docs/html/images/brand/en_app_rgb_wo_45.png
new file mode 100644
index 0000000..9891cbb
--- /dev/null
+++ b/docs/html/images/brand/en_app_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/en_app_rgb_wo_60.png b/docs/html/images/brand/en_app_rgb_wo_60.png
new file mode 100644
index 0000000..649e782
--- /dev/null
+++ b/docs/html/images/brand/en_app_rgb_wo_60.png
Binary files differ
diff --git a/docs/html/images/brand/en_generic_rgb_wo_45.png b/docs/html/images/brand/en_generic_rgb_wo_45.png
new file mode 100644
index 0000000..73dd393
--- /dev/null
+++ b/docs/html/images/brand/en_generic_rgb_wo_45.png
Binary files differ
diff --git a/docs/html/images/brand/en_generic_rgb_wo_60.png b/docs/html/images/brand/en_generic_rgb_wo_60.png
new file mode 100644
index 0000000..9a50aff
--- /dev/null
+++ b/docs/html/images/brand/en_generic_rgb_wo_60.png
Binary files differ
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index af8b0c2..76edb0a 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -567,6 +567,42 @@
         return rsnScriptIntrinsicCreate(mContext, id, eid);
     }
 
+    native int  rsnScriptKernelIDCreate(int con, int sid, int slot, int sig);
+    synchronized int nScriptKernelIDCreate(int sid, int slot, int sig) {
+        validate();
+        return rsnScriptKernelIDCreate(mContext, sid, slot, sig);
+    }
+
+    native int  rsnScriptFieldIDCreate(int con, int sid, int slot);
+    synchronized int nScriptFieldIDCreate(int sid, int slot) {
+        validate();
+        return rsnScriptFieldIDCreate(mContext, sid, slot);
+    }
+
+    native int  rsnScriptGroupCreate(int con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
+    synchronized int nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+        validate();
+        return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
+    }
+
+    native void rsnScriptGroupSetInput(int con, int group, int kernel, int alloc);
+    synchronized void nScriptGroupSetInput(int group, int kernel, int alloc) {
+        validate();
+        rsnScriptGroupSetInput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupSetOutput(int con, int group, int kernel, int alloc);
+    synchronized void nScriptGroupSetOutput(int group, int kernel, int alloc) {
+        validate();
+        rsnScriptGroupSetOutput(mContext, group, kernel, alloc);
+    }
+
+    native void rsnScriptGroupExecute(int con, int group);
+    synchronized void nScriptGroupExecute(int group) {
+        validate();
+        rsnScriptGroupExecute(mContext, group);
+    }
+
     native int  rsnSamplerCreate(int con, int magFilter, int minFilter,
                                  int wrapS, int wrapT, int wrapR, float aniso);
     synchronized int nSamplerCreate(int magFilter, int minFilter,
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index bbf5e7e..3fe3261 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -16,10 +16,105 @@
 
 package android.renderscript;
 
+import android.util.SparseArray;
+
 /**
  *
  **/
 public class Script extends BaseObj {
+
+    /**
+     * KernelID is an identifier for a Script + root function pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getKernelID_funcname()".
+     *
+     */
+    public static final class KernelID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        int mSig;
+        KernelID(int id, RenderScript rs, Script s, int slot, int sig) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+            mSig = sig;
+        }
+    }
+
+    private final SparseArray<KernelID> mKIDs = new SparseArray<KernelID>();
+    /**
+     * Only to be used by generated reflected classes.
+     *
+     *
+     * @param slot
+     * @param sig
+     * @param ein
+     * @param eout
+     *
+     * @return KernelID
+     */
+    protected KernelID createKernelID(int slot, int sig, Element ein, Element eout) {
+        KernelID k = mKIDs.get(slot);
+        if (k != null) {
+            return k;
+        }
+
+        int id = mRS.nScriptKernelIDCreate(getID(mRS), slot, sig);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create KernelID");
+        }
+
+        k = new KernelID(id, mRS, this, slot, sig);
+        mKIDs.put(slot, k);
+        return k;
+    }
+
+    /**
+     * FieldID is an identifier for a Script + exported field pair. It is used
+     * as an identifier for ScriptGroup creation.
+     *
+     * This class should not be directly created. Instead use the method in the
+     * reflected or intrinsic code "getFieldID_funcname()".
+     *
+     */
+    public static final class FieldID extends BaseObj {
+        Script mScript;
+        int mSlot;
+        FieldID(int id, RenderScript rs, Script s, int slot) {
+            super(id, rs);
+            mScript = s;
+            mSlot = slot;
+        }
+    }
+
+    private final SparseArray<FieldID> mFIDs = new SparseArray();
+    /**
+     * Only to be used by generated reflected classes.
+     *
+     * @param slot
+     * @param e
+     *
+     * @return FieldID
+     */
+    protected FieldID createFieldID(int slot, Element e) {
+        FieldID f = mFIDs.get(slot);
+        if (f != null) {
+            return f;
+        }
+
+        int id = mRS.nScriptFieldIDCreate(getID(mRS), slot);
+        if (id == 0) {
+            throw new RSDriverException("Failed to create FieldID");
+        }
+
+        f = new FieldID(id, mRS, this, slot);
+        mFIDs.put(slot, f);
+        return f;
+    }
+
+
     /**
      * Only intended for use by generated reflected code.
      *
diff --git a/graphics/java/android/renderscript/ScriptGroup.java b/graphics/java/android/renderscript/ScriptGroup.java
index c4064b5..4efb45b 100644
--- a/graphics/java/android/renderscript/ScriptGroup.java
+++ b/graphics/java/android/renderscript/ScriptGroup.java
@@ -17,67 +17,60 @@
 package android.renderscript;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 
 /**
- * @hide
+ * ScriptGroup creates a groups of scripts which are executed
+ * together based upon upon one execution call as if they were
+ * all part of a single script.  The scripts may be connected
+ * internally or to an external allocation. For the internal
+ * connections the intermediate results are not observable after
+ * the execution of the script.
+ * <p>
+ * The external connections are grouped into inputs and outputs.
+ * All outputs are produced by a script kernel and placed into a
+ * user supplied allocation. Inputs are similar but supply the
+ * input of a kernal. Inputs bounds to a script are set directly
+ * upon the script.
+ *
  **/
-public class ScriptGroup extends BaseObj {
-    Node mNodes[];
-    Connection mConnections[];
-    Node mFirstNode;
+public final class ScriptGroup extends BaseObj {
     IO mOutputs[];
     IO mInputs[];
 
     static class IO {
-        Script mScript;
+        Script.KernelID mKID;
         Allocation mAllocation;
-        String mName;
 
-        IO(Script s) {
-            mScript = s;
-        }
-        IO(Script s, String n) {
-            mScript = s;
-            mName = n;
+        IO(Script.KernelID s) {
+            mKID = s;
         }
     }
 
-    static class Connection {
-        Node mTo[];
-        String mToName[];
-        Node mFrom;
-        Type mAllocationType;
-        Allocation mInternalAllocation;
-
-        Connection(Node out, Type t) {
-            mFrom = out;
+    static class ConnectLine {
+        ConnectLine(Type t, Script.KernelID from, Script.KernelID to) {
+            mFrom = from;
+            mToK = to;
             mAllocationType = t;
         }
 
-        void addTo(Node n, String name) {
-            if (mTo == null) {
-                mTo = new Node[1];
-                mToName = new String[1];
-            } else {
-                Node nt[] = new Node[mTo.length + 1];
-                String ns[] = new String[mTo.length + 1];
-                System.arraycopy(mTo, 0, nt, 0, mTo.length);
-                System.arraycopy(mToName, 0, ns, 0, mTo.length);
-                mTo = nt;
-                mToName = ns;
-            }
-            mTo[mTo.length - 1] = n;
-            mToName[mTo.length - 1] = name;
+        ConnectLine(Type t, Script.KernelID from, Script.FieldID to) {
+            mFrom = from;
+            mToF = to;
+            mAllocationType = t;
         }
+
+        Script.FieldID mToF;
+        Script.KernelID mToK;
+        Script.KernelID mFrom;
+        Type mAllocationType;
     }
 
     static class Node {
         Script mScript;
-        Connection mInput[] = new Connection[8];
-        Connection mOutput[] = new Connection[1];
-        int mInputCount;
-        int mOutputCount;
-        int mDepth;
+        ArrayList<Script.KernelID> mKernels = new ArrayList<Script.KernelID>();
+        ArrayList<ConnectLine> mInputs = new ArrayList<ConnectLine>();
+        ArrayList<ConnectLine> mOutputs = new ArrayList<ConnectLine>();
         boolean mSeen;
 
         Node mNext;
@@ -85,24 +78,6 @@
         Node(Script s) {
             mScript = s;
         }
-
-        void addInput(Connection c) {
-            if (mInput.length <= mInputCount) {
-                Connection[] nc = new Connection[mInput.length + 8];
-                System.arraycopy(mInput, 0, nc, 0, mInputCount);
-                mInput = nc;
-            }
-            mInput[mInputCount++] = c;
-        }
-
-        void addOutput(Connection c) {
-            if (mOutput.length <= mOutputCount) {
-                Connection[] nc = new Connection[mOutput.length + 8];
-                System.arraycopy(mOutput, 0, nc, 0, mOutputCount);
-                mOutput = nc;
-            }
-            mOutput[mOutputCount++] = c;
-        }
     }
 
 
@@ -110,276 +85,326 @@
         super(id, rs);
     }
 
-    void init(int nodeCount, int connectionCount) {
-        mNodes = new Node[nodeCount];
-        mConnections = new Connection[connectionCount];
-
-        android.util.Log.v("RSR", "init" + nodeCount + ", " + connectionCount);
-
-        // Count outputs and create array.
-        Node n = mFirstNode;
-        int outputCount = 0;
-        int inputCount = 0;
-        int connectionIndex = 0;
-        int nodeNum = 0;
-        while (n != null) {
-            mNodes[nodeNum++] = n;
-
-            // Look for unattached kernel inputs
-            boolean hasInput = false;
-            for (int ct=0; ct < n.mInput.length; ct++) {
-                if (n.mInput[ct] != null) {
-                    if (n.mInput[ct].mToName == null) {
-                        hasInput = true;
-                    }
-                }
-            }
-            if (!hasInput) {
-                if (mInputs == null) {
-                    mInputs = new IO[1];
-                }
-                if (mInputs.length <= inputCount) {
-                    IO t[] = new IO[mInputs.length + 1];
-                    System.arraycopy(mInputs, 0, t, 0, mInputs.length);
-                    mInputs = t;
-                }
-                mInputs[inputCount++] = new IO(n.mScript);
-            }
-
-            // Look for unattached kernel outputs
-            boolean hasOutput = false;
-            for (int ct=0; ct < n.mOutput.length; ct++) {
-                if (n.mOutput[ct] != null) {
-                    hasOutput = true;
-                }
-            }
-            if (!hasOutput) {
-                if (mOutputs == null) {
-                    mOutputs = new IO[1];
-                }
-                if (mOutputs.length <= outputCount) {
-                    IO t[] = new IO[mOutputs.length + 1];
-                    System.arraycopy(mOutputs, 0, t, 0, mOutputs.length);
-                    mOutputs = t;
-                }
-                mOutputs[outputCount++] = new IO(n.mScript);
-            }
-
-            // Make allocations for internal connections
-            // Since script outputs are unique, use those to avoid duplicates.
-            for (int ct=0; ct < n.mOutput.length; ct++) {
-                android.util.Log.v("RSR", "init out2 " + n.mOutput[ct]);
-                if (n.mOutput[ct] != null) {
-                    Connection t = n.mOutput[ct];
-                    mConnections[connectionIndex++] = t;
-                    t.mInternalAllocation = Allocation.createTyped(mRS, t.mAllocationType);
-                }
-            }
-
-            n = n.mNext;
-        }
-    }
-
-    public void setInput(Script s, Allocation a) {
+    /**
+     * Sets an input of the ScriptGroup. This specifies an
+     * Allocation to be used for the kernels which require a kernel
+     * input and that input is provided external to the group.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setInput(Script.KernelID s, Allocation a) {
         for (int ct=0; ct < mInputs.length; ct++) {
-            if (mInputs[ct].mScript == s) {
+            if (mInputs[ct].mKID == s) {
                 mInputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetInput(getID(mRS), s.getID(mRS), mRS.safeID(a));
                 return;
             }
         }
         throw new RSIllegalArgumentException("Script not found");
     }
 
-    public void setOutput(Script s, Allocation a) {
+    /**
+     * Sets an output of the ScriptGroup. This specifies an
+     * Allocation to be used for the kernels which require a kernel
+     * output and that output is provided external to the group.
+     *
+     * @param s The ID of the kernel where the allocation should be
+     *          connected.
+     * @param a The allocation to connect.
+     */
+    public void setOutput(Script.KernelID s, Allocation a) {
         for (int ct=0; ct < mOutputs.length; ct++) {
-            if (mOutputs[ct].mScript == s) {
+            if (mOutputs[ct].mKID == s) {
                 mOutputs[ct].mAllocation = a;
+                mRS.nScriptGroupSetOutput(getID(mRS), s.getID(mRS), mRS.safeID(a));
                 return;
             }
         }
         throw new RSIllegalArgumentException("Script not found");
     }
 
+    /**
+     * Execute the ScriptGroup.  This will run all the kernels in
+     * the script.  The state of the connecting lines will not be
+     * observable after this operation.
+     */
     public void execute() {
-        android.util.Log.v("RSR", "execute");
-        boolean more = true;
-        int depth = 0;
-        while (more) {
-            more = false;
-            for (int ct=0; ct < mNodes.length; ct++) {
-                if (mNodes[ct].mDepth == depth) {
-                    more = true;
-
-                    Allocation kernelIn = null;
-                    for (int ct2=0; ct2 < mNodes[ct].mInputCount; ct2++) {
-                        android.util.Log.v("RSR", " kin " + ct2 + ", to " + mNodes[ct].mInput[ct2].mTo[0] + ", name " + mNodes[ct].mInput[ct2].mToName[0]);
-                        if (mNodes[ct].mInput[ct2].mToName[0] == null) {
-                            kernelIn = mNodes[ct].mInput[ct2].mInternalAllocation;
-                            break;
-                        }
-                    }
-
-                    Allocation kernelOut= null;
-                    for (int ct2=0; ct2 < mNodes[ct].mOutputCount; ct2++) {
-                        android.util.Log.v("RSR", " kout " + ct2 + ", from " + mNodes[ct].mOutput[ct2].mFrom);
-                        if (mNodes[ct].mOutput[ct2].mFrom != null) {
-                            kernelOut = mNodes[ct].mOutput[ct2].mInternalAllocation;
-                            break;
-                        }
-                    }
-                    if (kernelOut == null) {
-                        for (int ct2=0; ct2 < mOutputs.length; ct2++) {
-                            if (mOutputs[ct2].mScript == mNodes[ct].mScript) {
-                                kernelOut = mOutputs[ct2].mAllocation;
-                                break;
-                            }
-                        }
-                    }
-
-                    android.util.Log.v("RSR", "execute calling " + mNodes[ct] + ", with " + kernelIn);
-                    if (kernelIn != null) {
-                        try {
-
-                            Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
-                                          new Class[] { Allocation.class, Allocation.class });
-                            m.invoke(mNodes[ct].mScript, new Object[] {kernelIn, kernelOut} );
-                        } catch (Throwable t) {
-                            android.util.Log.e("RSR", "execute error " + t);
-                        }
-                    } else {
-                        try {
-                            Method m = mNodes[ct].mScript.getClass().getMethod("forEach_root",
-                                          new Class[] { Allocation.class });
-                            m.invoke(mNodes[ct].mScript, new Object[] {kernelOut} );
-                        } catch (Throwable t) {
-                            android.util.Log.e("RSR", "execute error " + t);
-                        }
-                    }
-
-                }
-            }
-            depth ++;
-        }
-
+        mRS.nScriptGroupExecute(getID(mRS));
     }
 
 
-    public static class Builder {
-        RenderScript mRS;
-        Node mFirstNode;
-        int mConnectionCount = 0;
-        int mNodeCount = 0;
+    /**
+     * Create a ScriptGroup. There are two steps to creating a
+     * ScriptGoup.
+     * <p>
+     * First all the Kernels to be used by the group should be
+     * added.  Once this is done the kernels should be connected.
+     * Kernels cannot be added once a connection has been made.
+     * <p>
+     * Second, add connections. There are two forms of connections.
+     * Kernel to Kernel and Kernel to Field. Kernel to Kernel is
+     * higher performance and should be used where possible. The
+     * line of connections cannot form a loop. If a loop is detected
+     * an exception is thrown.
+     * <p>
+     * Once all the connections are made a call to create will
+     * return the ScriptGroup object.
+     *
+     */
+    public static final class Builder {
+        private RenderScript mRS;
+        private ArrayList<Node> mNodes = new ArrayList<Node>();
+        private ArrayList<ConnectLine> mLines = new ArrayList<ConnectLine>();
+        private int mKernelCount;
 
+        /**
+         * Create a builder for generating a ScriptGroup.
+         *
+         *
+         * @param rs The Renderscript context.
+         */
         public Builder(RenderScript rs) {
             mRS = rs;
         }
 
         private void validateRecurse(Node n, int depth) {
             n.mSeen = true;
-            if (depth > n.mDepth) {
-                n.mDepth = depth;
-            }
 
-            android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputCount);
-            for (int ct=0; ct < n.mOutputCount; ct++) {
-                for (int ct2=0; ct2 < n.mOutput[ct].mTo.length; ct2++) {
-                    if (n.mOutput[ct].mTo[ct2].mSeen) {
+            //android.util.Log.v("RSR", " validateRecurse outputCount " + n.mOutputs.size());
+            for (int ct=0; ct < n.mOutputs.size(); ct++) {
+                final ConnectLine cl = n.mOutputs.get(ct);
+                if (cl.mToK != null) {
+                    Node tn = findNode(cl.mToK.mScript);
+                    if (tn.mSeen) {
                         throw new RSInvalidStateException("Loops in group not allowed.");
                     }
-                    validateRecurse(n.mOutput[ct].mTo[ct2], depth + 1);
+                    validateRecurse(tn, depth + 1);
+                }
+                if (cl.mToF != null) {
+                    Node tn = findNode(cl.mToF.mScript);
+                    if (tn.mSeen) {
+                        throw new RSInvalidStateException("Loops in group not allowed.");
+                    }
+                    validateRecurse(tn, depth + 1);
                 }
             }
         }
 
         private void validate() {
-            android.util.Log.v("RSR", "validate");
-            Node n = mFirstNode;
-            while (n != null) {
-                n.mSeen = false;
-                n.mDepth = 0;
-                n = n.mNext;
-            }
+            //android.util.Log.v("RSR", "validate");
 
-            n = mFirstNode;
-            while (n != null) {
-                android.util.Log.v("RSR", "validate n= " + n);
-                if ((n.mSeen == false) && (n.mInputCount == 0)) {
-                    android.util.Log.v("RSR", " recursing " + n);
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                for (int ct2=0; ct2 < mNodes.size(); ct2++) {
+                    mNodes.get(ct2).mSeen = false;
+                }
+                Node n = mNodes.get(ct);
+                if (n.mInputs.size() == 0) {
                     validateRecurse(n, 0);
                 }
-                n = n.mNext;
             }
         }
 
-        private Node findScript(Script s) {
-            Node n = mFirstNode;
-            while (n != null) {
-                if (n.mScript == s) {
-                    return n;
+        private Node findNode(Script s) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                if (s == mNodes.get(ct).mScript) {
+                    return mNodes.get(ct);
                 }
-                n = n.mNext;
             }
             return null;
         }
 
-        private void addNode(Node n) {
-            n.mNext = mFirstNode;
-            mFirstNode = n;
-        }
-
-        public Builder addConnection(Type t, Script output, Script input, String inputName) {
-            android.util.Log.v("RSR", "addConnection " + t +", " + output + ", " + input);
-
-            // Look for existing output
-            Node nout = findScript(output);
-            Connection c;
-            if (nout == null) {
-                // Make new node
-                android.util.Log.v("RSR", "addConnection new output node");
-                nout = new Node(output);
-                mNodeCount++;
-                c = new Connection(nout, t);
-                mConnectionCount++;
-                nout.addOutput(c);
-                addNode(nout);
-            } else {
-                // Add to existing node
-                android.util.Log.v("RSR", "addConnection reuse output node");
-                if (nout.mOutput[0] != null) {
-                    if (nout.mOutput[0].mFrom.mScript != output) {
-                        throw new RSInvalidStateException("Changed output of existing node");
-                    }
-                    if (nout.mOutput[0].mAllocationType != t) {
-                        throw new RSInvalidStateException("Changed output type of existing node");
+        private Node findNode(Script.KernelID k) {
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    if (k == n.mKernels.get(ct2)) {
+                        return n;
                     }
                 }
-                c = nout.mOutput[0];
             }
-            // At this point we should have a connection attached to a script ouput.
+            return null;
+        }
 
-            // Find input
-            Node nin = findScript(input);
-            if (nin == null) {
-                android.util.Log.v("RSR", "addConnection new input node");
-                nin = new Node(input);
-                mNodeCount++;
-                addNode(nin);
+        /**
+         * Adds a Kernel to the group.
+         *
+         *
+         * @param k The kernel to add.
+         *
+         * @return Builder Returns this.
+         */
+        public Builder addKernel(Script.KernelID k) {
+            if (mLines.size() != 0) {
+                throw new RSInvalidStateException(
+                    "Kernels may not be added once connections exist.");
             }
-            c.addTo(nin, inputName);
-            nin.addInput(c);
+
+            //android.util.Log.v("RSR", "addKernel 1 k=" + k);
+            if (findNode(k) != null) {
+                return this;
+            }
+            //android.util.Log.v("RSR", "addKernel 2 ");
+            mKernelCount++;
+            Node n = findNode(k.mScript);
+            if (n == null) {
+                //android.util.Log.v("RSR", "addKernel 3 ");
+                n = new Node(k.mScript);
+                mNodes.add(n);
+            }
+            n.mKernels.add(k);
+            return this;
+        }
+
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes on the source side
+         *          of this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From kernel not found.");
+            }
+
+            Node nt = findNode(to.mScript);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
 
             validate();
             return this;
         }
 
+        /**
+         * Adds a connection to the group.
+         *
+         *
+         * @param t The type of the connection. This is used to
+         *          determine the kernel launch sizes for both sides of
+         *          this connection.
+         * @param from The source for the connection.
+         * @param to The destination of the connection.
+         *
+         * @return Builder Returns this
+         */
+        public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
+            //android.util.Log.v("RSR", "addConnection " + t +", " + from + ", " + to);
+
+            Node nf = findNode(from);
+            if (nf == null) {
+                throw new RSInvalidStateException("From kernel not found.");
+            }
+
+            Node nt = findNode(to);
+            if (nt == null) {
+                throw new RSInvalidStateException("To script not found.");
+            }
+
+            ConnectLine cl = new ConnectLine(t, from, to);
+            mLines.add(new ConnectLine(t, from, to));
+
+            nf.mOutputs.add(cl);
+            nt.mInputs.add(cl);
+
+            validate();
+            return this;
+        }
+
+
+
+        /**
+         * Creates the Script group.
+         *
+         *
+         * @return ScriptGroup The new ScriptGroup
+         */
         public ScriptGroup create() {
-            ScriptGroup sg = new ScriptGroup(0, mRS);
-            sg.mFirstNode = mFirstNode;
-            mFirstNode = null;
+            ArrayList<IO> inputs = new ArrayList<IO>();
+            ArrayList<IO> outputs = new ArrayList<IO>();
 
-            android.util.Log.v("RSR", "create nodes= " + mNodeCount + ", Connections= " + mConnectionCount);
+            int[] kernels = new int[mKernelCount];
+            int idx = 0;
+            for (int ct=0; ct < mNodes.size(); ct++) {
+                Node n = mNodes.get(ct);
+                for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
+                    final Script.KernelID kid = n.mKernels.get(ct2);
+                    kernels[idx++] = kid.getID(mRS);
 
-            sg.init(mNodeCount, mConnectionCount);
+                    boolean hasInput = false;
+                    boolean hasOutput = false;
+                    for (int ct3=0; ct3 < n.mInputs.size(); ct3++) {
+                        if (n.mInputs.get(ct3).mToK == kid) {
+                            hasInput = true;
+                        }
+                    }
+                    for (int ct3=0; ct3 < n.mOutputs.size(); ct3++) {
+                        if (n.mOutputs.get(ct3).mFrom == kid) {
+                            hasOutput = true;
+                        }
+                    }
+                    if (!hasInput) {
+                        inputs.add(new IO(kid));
+                    }
+                    if (!hasOutput) {
+                        outputs.add(new IO(kid));
+                    }
+
+                }
+            }
+            if (idx != mKernelCount) {
+                throw new RSRuntimeException("Count mismatch, should not happen.");
+            }
+
+            int[] src = new int[mLines.size()];
+            int[] dstk = new int[mLines.size()];
+            int[] dstf = new int[mLines.size()];
+            int[] types = new int[mLines.size()];
+
+            for (int ct=0; ct < mLines.size(); ct++) {
+                ConnectLine cl = mLines.get(ct);
+                src[ct] = cl.mFrom.getID(mRS);
+                if (cl.mToK != null) {
+                    dstk[ct] = cl.mToK.getID(mRS);
+                }
+                if (cl.mToF != null) {
+                    dstf[ct] = cl.mToF.getID(mRS);
+                }
+                types[ct] = cl.mAllocationType.getID(mRS);
+            }
+
+            int id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
+            if (id == 0) {
+                throw new RSRuntimeException("Object creation error, should not happen.");
+            }
+
+            ScriptGroup sg = new ScriptGroup(id, mRS);
+            sg.mOutputs = new IO[outputs.size()];
+            for (int ct=0; ct < outputs.size(); ct++) {
+                sg.mOutputs[ct] = outputs.get(ct);
+            }
+
+            sg.mInputs = new IO[inputs.size()];
+            for (int ct=0; ct < inputs.size(); ct++) {
+                sg.mInputs[ct] = inputs.get(ct);
+            }
+
             return sg;
         }
 
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
index 8d093a7..61e5d4f 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -91,5 +91,22 @@
         forEach(0, null, aout, null);
     }
 
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
 }
 
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
index 933a4dd..cb458ba 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicColorMatrix.java
@@ -154,5 +154,14 @@
         forEach(0, ain, aout, null);
     }
 
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
+
 }
 
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
index fb2948d..d7e9f32 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -103,5 +103,23 @@
         forEach(0, null, aout, null);
     }
 
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
+
 }
 
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
index 8599426..ff31270 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve5x5.java
@@ -98,5 +98,22 @@
         forEach(0, null, aout, null);
     }
 
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 2, null, null);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(1, null);
+    }
 }
 
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
index e45c0fd..188e04c 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicLUT.java
@@ -134,5 +134,13 @@
         forEach(0, ain, aout, null);
     }
 
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID() {
+        return createKernelID(0, 3, null, null);
+    }
 }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 2109a01..3f642e8 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1078,6 +1078,75 @@
     return (jint)rsScriptIntrinsicCreate(con, id, (RsElement)eid);
 }
 
+static jint
+nScriptKernelIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot, jint sig)
+{
+    LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", con, (void *)sid, slot, sig);
+    return (jint)rsScriptKernelIDCreate(con, (RsScript)sid, slot, sig);
+}
+
+static jint
+nScriptFieldIDCreate(JNIEnv *_env, jobject _this, RsContext con, jint sid, jint slot)
+{
+    LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", con, (void *)sid, slot);
+    return (jint)rsScriptFieldIDCreate(con, (RsScript)sid, slot);
+}
+
+static jint
+nScriptGroupCreate(JNIEnv *_env, jobject _this, RsContext con, jintArray _kernels, jintArray _src,
+    jintArray _dstk, jintArray _dstf, jintArray _types)
+{
+    LOG_API("nScriptGroupCreate, con(%p)", con);
+
+    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
+    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
+    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
+    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
+    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
+    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
+    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
+    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
+    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
+    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
+
+    int id = (int)rsScriptGroupCreate(con,
+                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
+                               (RsScriptKernelID *)srcPtr, srcLen,
+                               (RsScriptKernelID *)dstkPtr, dstkLen,
+                               (RsScriptFieldID *)dstfPtr, dstfLen,
+                               (RsType *)typesPtr, typesLen);
+
+    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
+    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
+    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
+    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
+    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
+    return id;
+}
+
+static void
+nScriptGroupSetInput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
+{
+    LOG_API("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetInput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupSetOutput(JNIEnv *_env, jobject _this, RsContext con, jint gid, jint kid, jint alloc)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", con,
+        (void *)gid, (void *)kid, (void *)alloc);
+    rsScriptGroupSetOutput(con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc);
+}
+
+static void
+nScriptGroupExecute(JNIEnv *_env, jobject _this, RsContext con, jint gid)
+{
+    LOG_API("nScriptGroupSetOutput, con(%p) group(%p)", con, (void *)gid);
+    rsScriptGroupExecute(con, (RsScriptGroup)gid);
+}
+
 // ---------------------------------------------------------------------------
 
 static jint
@@ -1420,6 +1489,12 @@
 
 {"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;[BI)I",  (void*)nScriptCCreate },
 {"rsnScriptIntrinsicCreate",         "(III)I",                                (void*)nScriptIntrinsicCreate },
+{"rsnScriptKernelIDCreate",          "(IIII)I",                               (void*)nScriptKernelIDCreate },
+{"rsnScriptFieldIDCreate",           "(III)I",                                (void*)nScriptFieldIDCreate },
+{"rsnScriptGroupCreate",             "(I[I[I[I[I[I)I",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroupSetInput",           "(IIII)V",                               (void*)nScriptGroupSetInput },
+{"rsnScriptGroupSetOutput",          "(IIII)V",                               (void*)nScriptGroupSetOutput },
+{"rsnScriptGroupExecute",            "(II)V",                                 (void*)nScriptGroupExecute },
 
 {"rsnProgramStoreCreate",            "(IZZZZZZIII)I",                         (void*)nProgramStoreCreate },
 
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index bd65b9e..487585e 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -490,6 +490,7 @@
             MtpConstants.FORMAT_MPEG,
             MtpConstants.FORMAT_EXIF_JPEG,
             MtpConstants.FORMAT_TIFF_EP,
+            MtpConstants.FORMAT_BMP,
             MtpConstants.FORMAT_GIF,
             MtpConstants.FORMAT_JFIF,
             MtpConstants.FORMAT_PNG,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index e7f98de..ed9bb97 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -98,7 +98,9 @@
         mWakeLock.acquire();
     }
 
-    public void onStop(Bundle icicle) {
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
         mWakeLock.release();
     }
 
diff --git a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
old mode 100755
new mode 100644
index 312b6fb..24c2a0d
--- a/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
+++ b/media/tests/contents/media_api/music/sine_200+1000Hz_44K_mo.wav
Binary files differ
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a0ae9e3..9839c16 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -344,7 +344,12 @@
         String notify = uri.getQueryParameter("notify");
         if (notify == null || "true".equals(notify)) {
             final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
-            getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            final long oldId = Binder.clearCallingIdentity();
+            try {
+                getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            } finally {
+                Binder.restoreCallingIdentity(oldId);
+            }
             if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
         } else {
             if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 60896c3..409a00e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -42,23 +42,6 @@
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
         />
 
-    <com.android.systemui.statusbar.RotationToggle android:id="@+id/rotation_lock_button"
-        android:layout_width="32dp"
-        android:layout_height="32dp"
-        android:layout_margin="8dp"
-        android:button="@drawable/ic_notify_rotation"
-        android:contentDescription="@string/accessibility_rotation_lock_off"
-        android:clickable="true"
-        />
-
-    <ImageView android:id="@+id/settings_button"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:scaleType="center"
-        android:src="@drawable/ic_notify_quicksettings"
-        android:contentDescription="@string/accessibility_settings_button"
-        />
-
     <Space
         android:layout_width="0dp"
         android:layout_height="0dp"
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 ca1f82a..8f6a903 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -177,7 +177,6 @@
     // top bar
     View mClearButton;
     View mSettingsButton;
-    RotationToggle mRotationButton;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
@@ -365,8 +364,9 @@
         mClearButton.setEnabled(false);
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
         mSettingsButton = mStatusBarWindow.findViewById(R.id.settings_button);
-        mSettingsButton.setOnClickListener(mSettingsButtonListener);
-        mRotationButton = (RotationToggle) mStatusBarWindow.findViewById(R.id.rotation_lock_button);
+        if (mSettingsButton != null) {
+            mSettingsButton.setOnClickListener(mSettingsButtonListener);
+        }
         
         mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
         mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
@@ -819,7 +819,9 @@
             }
         }
 
-        mSettingsButton.setEnabled(isDeviceProvisioned());
+        if (mSettingsButton != null) {
+            mSettingsButton.setEnabled(isDeviceProvisioned());
+        }
     }
 
     @Override
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 8fe28a3..47ec243 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -667,8 +667,12 @@
     private void addWidget(int appId) {
         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
         AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appId);
-        AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
-        addWidget(view);
+        if (appWidgetInfo != null) {
+            AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+            addWidget(view);
+        } else {
+            Log.w(TAG, "AppWidgetInfo was null; not adding widget id " + appId);
+        }
     }
 
     private void maybePopulateWidgets() {
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index f4ad756..f960833 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -353,7 +353,7 @@
 
         while (it.hasNext()) {
             Alarm alarm = it.next();
-            if (UserHandle.getUserId(alarm.operation.getTargetUid()) == userHandle) {
+            if (UserHandle.getUserId(alarm.operation.getCreatorUid()) == userHandle) {
                 it.remove();
             }
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index db042b5..ce5424b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -11438,7 +11438,7 @@
                     // Add the new results to the existing results, tracking
                     // and de-dupping single user receivers.
                     for (int i=0; i<newReceivers.size(); i++) {
-                        ResolveInfo ri = receivers.get(i);
+                        ResolveInfo ri = newReceivers.get(i);
                         if ((ri.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) {
                             ComponentName cn = new ComponentName(
                                     ri.activityInfo.packageName, ri.activityInfo.name);
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 1b6ff7a..b0af081 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -965,12 +965,12 @@
                 if (!printed) {
                     if (needSep) {
                         pw.println();
-                        needSep = false;
                     }
+                    needSep = true;
                     printed = true;
                     pw.println("  Active broadcasts [" + mQueueName + "]:");
                 }
-                pw.println("  Broadcast #" + i + ":");
+                pw.println("  Active Broadcast " + mQueueName + " #" + i + ":");
                 br.dump(pw, "    ");
             }
             printed = false;
@@ -985,9 +985,10 @@
                         pw.println();
                     }
                     needSep = true;
+                    printed = true;
                     pw.println("  Active ordered broadcasts [" + mQueueName + "]:");
                 }
-                pw.println("  Ordered Broadcast #" + i + ":");
+                pw.println("  Active Ordered Broadcast " + mQueueName + " #" + i + ":");
                 mOrderedBroadcasts.get(i).dump(pw, "    ");
             }
             if (dumpPackage == null || (mPendingBroadcast != null
@@ -1023,7 +1024,8 @@
                 printed = true;
             }
             if (dumpAll) {
-                pw.print("  Historical Broadcast #"); pw.print(i); pw.println(":");
+                pw.print("  Historical Broadcast " + mQueueName + " #");
+                        pw.print(i); pw.println(":");
                 r.dump(pw, "    ");
             } else {
                 if (i >= 50) {
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index 3bc19a1..328f687 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -486,7 +486,7 @@
             WifiP2pConfig config = new WifiP2pConfig();
             config.deviceAddress = mConnectingDevice.deviceAddress;
             // Helps with STA & P2P concurrency
-            config.groupOwnerIntent = WifiP2pConfig.MAX_GO_INTENT;
+            config.groupOwnerIntent = WifiP2pConfig.MAX_GROUP_OWNER_INTENT;
 
             final WifiDisplay display = createWifiDisplay(mConnectingDevice);
             mHandler.post(new Runnable() {
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 690d7c9..be86628 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -29,6 +29,8 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -188,30 +190,35 @@
                 writeUserLocked(info);
             }
         }
+        sendUserInfoChangedBroadcast(userId);
     }
 
     @Override
-    public ParcelFileDescriptor setUserIcon(int userId) {
+    public void setUserIcon(int userId, Bitmap bitmap) {
         checkManageUsersPermission("update users");
         synchronized (mPackagesLock) {
             UserInfo info = mUsers.get(userId);
-            if (info == null) return null;
-            ParcelFileDescriptor fd = openIconBitmapLocked(info, true /* write */);
-            if (fd != null) {
-                writeUserLocked(info);
-            }
-            return fd;
+            if (info == null) return;
+            writeBitmapLocked(info, bitmap);
+            writeUserLocked(info);
         }
+        sendUserInfoChangedBroadcast(userId);
+    }
+
+    private void sendUserInfoChangedBroadcast(int userId) {
+        Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
+        changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+        changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mContext.sendBroadcastAsUser(changedIntent, new UserHandle(userId));
     }
 
     @Override
-    public ParcelFileDescriptor getUserIcon(int userId) {
+    public Bitmap getUserIcon(int userId) {
         checkManageUsersPermission("read users");
         synchronized (mPackagesLock) {
             UserInfo info = mUsers.get(userId);
             if (info == null || info.iconPath == null) return null;
-            ParcelFileDescriptor fd = openIconBitmapLocked(info, false /* read */);
-            return fd;
+            return BitmapFactory.decodeFile(info.iconPath);
         }
     }
 
@@ -289,7 +296,7 @@
         }
     }
 
-    private ParcelFileDescriptor openIconBitmapLocked(UserInfo info, boolean toWrite) {
+    private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
         try {
             File dir = new File(mUsersDir, Integer.toString(info.id));
             File file = new File(dir, USER_PHOTO_FILENAME);
@@ -300,16 +307,18 @@
                         FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                         -1, -1);
             }
-            ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
-                    toWrite ? MODE_CREATE|MODE_READ_WRITE : MODE_READ_WRITE);
-            if (toWrite) {
+            FileOutputStream os;
+            if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
                 info.iconPath = file.getAbsolutePath();
             }
-            return fd;
+            try {
+                os.close();
+            } catch (IOException ioe) {
+                // What the ... !
+            }
         } catch (FileNotFoundException e) {
             Slog.w(LOG_TAG, "Error setting photo for user ", e);
         }
-        return null;
     }
 
     /**
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java
index 732da4e..29c204c 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/GroupTest.java
@@ -21,16 +21,16 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.RenderScript;
-import android.renderscript.Script;
-import android.renderscript.ScriptC;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
 import android.renderscript.Type;
 import android.renderscript.Matrix4f;
 import android.renderscript.ScriptGroup;
 import android.util.Log;
 
 public class GroupTest extends TestBase {
-    private ScriptC_convolve3x3 mConvolve;
-    private ScriptC_colormatrix mMatrix;
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
 
     private Allocation mScratchPixelsAllocation1;
     private ScriptGroup mGroup;
@@ -48,20 +48,20 @@
         mWidth = mInPixelsAllocation.getType().getX();
         mHeight = mInPixelsAllocation.getType().getY();
 
-        mConvolve = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
-        mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
 
         float f[] = new float[9];
         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
-        mConvolve.set_gCoeffs(f);
+        mConvolve.setCoefficients(f);
 
         Matrix4f m = new Matrix4f();
         m.set(1, 0, 0.2f);
         m.set(1, 1, 0.9f);
         m.set(1, 2, 0.2f);
-        mMatrix.invoke_setMatrix(m);
+        mMatrix.setColorMatrix(m);
 
         Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
         tb.setX(mWidth);
@@ -70,24 +70,23 @@
 
         if (mUseNative) {
             ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
-            b.addConnection(connect, mConvolve, mMatrix, null);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
             mGroup = b.create();
-
         } else {
             mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
         }
     }
 
     public void runTest() {
-        mConvolve.set_gIn(mInPixelsAllocation);
-        mConvolve.set_gWidth(mWidth);
-        mConvolve.set_gHeight(mHeight);
+        mConvolve.setInput(mInPixelsAllocation);
         if (mUseNative) {
-            mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
             mGroup.execute();
         } else {
-            mConvolve.forEach_root(mScratchPixelsAllocation1);
-            mMatrix.forEach_root(mScratchPixelsAllocation1, mOutPixelsAllocation);
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
         }
     }
 
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9fe1c60..4aa092b 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -75,6 +75,7 @@
 import android.util.Log;
 import android.util.LruCache;
 
+import com.android.internal.R;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
@@ -112,6 +113,7 @@
     private ConnectivityManager mCm;
 
     private final boolean mP2pSupported;
+    private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
     private final String mPrimaryDeviceType;
 
     /* Scan results handling */
@@ -595,16 +597,16 @@
         mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
 
         mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_wifi_framework_scan_interval);
+                R.integer.config_wifi_framework_scan_interval);
 
         mDriverStopDelayMs = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_wifi_driver_stop_delay);
+                R.integer.config_wifi_driver_stop_delay);
 
         mBackgroundScanSupported = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_wifi_background_scan_support);
+                R.bool.config_wifi_background_scan_support);
 
         mPrimaryDeviceType = mContext.getResources().getString(
-                com.android.internal.R.string.config_wifi_p2p_device_type);
+                R.string.config_wifi_p2p_device_type);
 
         mUserWantsSuspendOpt.set(Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
@@ -2011,6 +2013,10 @@
                     replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
                             WifiManager.BUSY);
                     break;
+                case WifiP2pService.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    break;
                 default:
                     loge("Error! unhandled message" + message);
                     break;
@@ -2408,7 +2414,7 @@
             mNetworkInfo.setIsAvailable(true);
 
             int defaultInterval = mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_wifi_supplicant_scan_interval);
+                    R.integer.config_wifi_supplicant_scan_interval);
 
             mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
                     Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
@@ -3486,7 +3492,7 @@
              * The scans are useful to notify the user of the presence of an open network.
              * Note that these are not wake up scans.
              */
-            if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+            if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {
                 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
                             ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
             }
@@ -3497,6 +3503,7 @@
             boolean ret = HANDLED;
             switch (message.what) {
                 case CMD_NO_NETWORKS_PERIODIC_SCAN:
+                    if (mP2pConnected.get()) break;
                     if (message.arg1 == mPeriodicScanToken &&
                             mWifiConfigStore.getConfiguredNetworks().size() == 0) {
                         sendMessage(CMD_START_SCAN);
@@ -3557,6 +3564,21 @@
                     /* Handled in parent state */
                     ret = NOT_HANDLED;
                     break;
+                case WifiP2pService.P2P_CONNECTION_CHANGED:
+                    NetworkInfo info = (NetworkInfo) message.obj;
+                    mP2pConnected.set(info.isConnected());
+                    if (mP2pConnected.get()) {
+                        int defaultInterval = mContext.getResources().getInteger(
+                                R.integer.config_wifi_scan_interval_p2p_connected);
+                        long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
+                                Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                                defaultInterval);
+                        mWifiNative.setScanInterval((int) scanIntervalMs/1000);
+                    } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
+                        if (DBG) log("Turn on scanning after p2p disconnected");
+                        sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
+                                    ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
+                    }
                 default:
                     ret = NOT_HANDLED;
             }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 213fab9..f4440c8 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -38,7 +38,7 @@
     public WpsInfo wps;
 
     /** @hide */
-    public static final int MAX_GO_INTENT   =   15;
+    public static final int MAX_GROUP_OWNER_INTENT   =   15;
 
     /**
      * This is an integer value between 0 and 15 where 0 indicates the least
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index a42470f..dfe1297 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -135,19 +135,7 @@
     private static final int DISCOVER_TIMEOUT_S = 120;
 
     /* Idle time after a peer is gone when the group is torn down */
-    private static final int GROUP_IDLE_TIME_S = 25;
-
-    /**
-     * Delay between restarts upon failure to setup connection with supplicant
-     */
-    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
-
-    /**
-     * Number of times we attempt to restart p2p
-     */
-    private static final int P2P_RESTART_TRIES = 5;
-
-    private int mP2pRestartCount = 0;
+    private static final int GROUP_IDLE_TIME_S = 20;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
@@ -159,6 +147,9 @@
     /* User rejected a peer request */
     private static final int PEER_CONNECTION_USER_REJECT    =   BASE + 3;
 
+    /* Commands to the WifiStateMachine */
+    public static final int P2P_CONNECTION_CHANGED         =   BASE + 11;
+
     private final boolean mP2pSupported;
 
     private WifiP2pDevice mThisDevice = new WifiP2pDevice();
@@ -1221,13 +1212,10 @@
                                 mGroup.getNetworkName()));
                     }
 
+                    mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
                     if (mGroup.isGroupOwner()) {
                         startDhcpServer(mGroup.getInterface());
                     } else {
-                        // Set group idle only for a client on the group interface to speed up
-                        // disconnect when GO is gone. Setting group idle time for a group owner
-                        // causes connectivity issues for new clients
-                        mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
                         mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
                                 P2pStateMachine.this, mGroup.getInterface());
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
@@ -1292,7 +1280,6 @@
             //DHCP server has already been started if I am a group owner
             if (mGroup.isGroupOwner()) {
                 setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
-                sendP2pConnectionChangedBroadcast();
             }
         }
 
@@ -1315,6 +1302,7 @@
                     } else {
                         loge("Connect on null device address, ignore");
                     }
+                    sendP2pConnectionChangedBroadcast();
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
                     device = (WifiP2pDevice) message.obj;
@@ -1597,6 +1585,8 @@
         intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo));
         intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        mWifiChannel.sendMessage(WifiP2pService.P2P_CONNECTION_CHANGED,
+                new NetworkInfo(mNetworkInfo));
     }
 
     private void sendP2pPersistentGroupsChangedBroadcast() {