Merge "Use a larger scaling span for larger screen devices." into jb-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index f0148b4..4abcaee 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);
@@ -16594,7 +16581,6 @@
 
   public class UserManager {
     method public java.lang.String getUserName();
-    method public boolean supportsMultipleUsers();
   }
 
   public abstract class Vibrator {
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/ContentResolver.java b/core/java/android/content/ContentResolver.java
index ece8841..cd1e882 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1219,9 +1219,16 @@
     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
             ContentObserver observer)
     {
+        registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
+    }
+
+    /** @hide - designated user version */
+    public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
+            ContentObserver observer, int userHandle)
+    {
         try {
             getContentService().registerContentObserver(uri, notifyForDescendents,
-                    observer.getContentObserver());
+                    observer.getContentObserver(), userHandle);
         } catch (RemoteException e) {
         }
     }
@@ -1276,10 +1283,21 @@
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
     public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+        notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
+    }
+
+    /**
+     * Notify registered observers within the designated user(s) that a row was updated.
+     *
+     * @hide
+     */
+    public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
+            int userHandle) {
         try {
             getContentService().notifyChange(
                     uri, observer == null ? null : observer.getContentObserver(),
-                    observer != null && observer.deliverSelfNotifications(), syncToNetwork);
+                    observer != null && observer.deliverSelfNotifications(), syncToNetwork,
+                    userHandle);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 472fe94..0f6488a 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.app.ActivityManager;
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
@@ -33,6 +34,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -138,17 +140,47 @@
         getSyncManager();
     }
 
-    public void registerContentObserver(Uri uri, boolean notifyForDescendents,
-            IContentObserver observer) {
+    /**
+     * Register a content observer tied to a specific user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be observed.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly handled; all other pseudousers are forbidden.
+     */
+    @Override
+    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+            IContentObserver observer, int userHandle) {
         if (observer == null || uri == null) {
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
-        synchronized (mRootNode) {
-            mRootNode.addObserverLocked(uri, observer, notifyForDescendents, mRootNode,
-                    Binder.getCallingUid(), Binder.getCallingPid());
-            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
-                    " with notifyForDescendents " + notifyForDescendents);
+
+        final int callingUser = UserHandle.getCallingUserId();
+        if (callingUser != userHandle) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "no permission to observe other users' provider view");
         }
+
+        if (userHandle < 0) {
+            if (userHandle == UserHandle.USER_CURRENT) {
+                userHandle = ActivityManager.getCurrentUser();
+            } else if (userHandle != UserHandle.USER_ALL) {
+                throw new InvalidParameterException("Bad user handle for registerContentObserver: "
+                        + userHandle);
+            }
+        }
+
+        synchronized (mRootNode) {
+            mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
+                    Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
+            if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
+                    " with notifyForDescendants " + notifyForDescendants);
+        }
+    }
+
+    public void registerContentObserver(Uri uri, boolean notifyForDescendants,
+            IContentObserver observer) {
+        registerContentObserver(uri, notifyForDescendants, observer,
+                UserHandle.getCallingUserId());
     }
 
     public void unregisterContentObserver(IContentObserver observer) {
@@ -161,14 +193,39 @@
         }
     }
 
+    /**
+     * Notify observers of a particular user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be notified.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly interpreted; no other pseudousers are allowed.
+     */
+    @Override
     public void notifyChange(Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+            boolean observerWantsSelfNotifications, boolean syncToNetwork,
+            int userHandle) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "Notifying update of " + uri + " from observer " + observer
-                    + ", syncToNetwork " + syncToNetwork);
+            Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
+                    + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
         }
 
-        int userId = UserHandle.getCallingUserId();
+        // Notify for any user other than the caller's own requires permission.
+        final int callingUserHandle = UserHandle.getCallingUserId();
+        if (userHandle != callingUserHandle) {
+            mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "no permission to notify other users");
+        }
+
+        // We passed the permission check; resolve pseudouser targets as appropriate
+        if (userHandle < 0) {
+            if (userHandle == UserHandle.USER_CURRENT) {
+                userHandle = ActivityManager.getCurrentUser();
+            } else if (userHandle != UserHandle.USER_ALL) {
+                throw new InvalidParameterException("Bad user handle for notifyChange: "
+                        + userHandle);
+            }
+        }
+
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
@@ -176,7 +233,7 @@
             ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
             synchronized (mRootNode) {
                 mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
-                        calls);
+                        userHandle, calls);
             }
             final int numCalls = calls.size();
             for (int i=0; i<numCalls; i++) {
@@ -207,7 +264,7 @@
             if (syncToNetwork) {
                 SyncManager syncManager = getSyncManager();
                 if (syncManager != null) {
-                    syncManager.scheduleLocalSync(null /* all accounts */, userId,
+                    syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
                             uri.getAuthority());
                 }
             }
@@ -216,6 +273,12 @@
         }
     }
 
+    public void notifyChange(Uri uri, IContentObserver observer,
+            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+        notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
+                UserHandle.getCallingUserId());
+    }
+
     /**
      * Hide this class since it is not part of api,
      * but current unittest framework requires it to be public
@@ -543,16 +606,18 @@
             public final IContentObserver observer;
             public final int uid;
             public final int pid;
-            public final boolean notifyForDescendents;
+            public final boolean notifyForDescendants;
+            private final int userHandle;
             private final Object observersLock;
 
             public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
-                    int _uid, int _pid) {
+                    int _uid, int _pid, int _userHandle) {
                 this.observersLock = observersLock;
                 observer = o;
                 uid = _uid;
                 pid = _pid;
-                notifyForDescendents = n;
+                userHandle = _userHandle;
+                notifyForDescendants = n;
                 try {
                     observer.asBinder().linkToDeath(this, 0);
                 } catch (RemoteException e) {
@@ -571,7 +636,8 @@
                 pidCounts.put(pid, pidCounts.get(pid)+1);
                 pw.print(prefix); pw.print(name); pw.print(": pid=");
                         pw.print(pid); pw.print(" uid=");
-                        pw.print(uid); pw.print(" target=");
+                        pw.print(uid); pw.print(" user=");
+                        pw.print(userHandle); pw.print(" target=");
                         pw.println(Integer.toHexString(System.identityHashCode(
                                 observer != null ? observer.asBinder() : null)));
             }
@@ -639,17 +705,21 @@
             return uri.getPathSegments().size() + 1;
         }
 
+        // Invariant:  userHandle is either a hard user number or is USER_ALL
         public void addObserverLocked(Uri uri, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
-            addObserverLocked(uri, 0, observer, notifyForDescendents, observersLock, uid, pid);
+                boolean notifyForDescendants, Object observersLock,
+                int uid, int pid, int userHandle) {
+            addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
+                    uid, pid, userHandle);
         }
 
         private void addObserverLocked(Uri uri, int index, IContentObserver observer,
-                boolean notifyForDescendents, Object observersLock, int uid, int pid) {
+                boolean notifyForDescendants, Object observersLock,
+                int uid, int pid, int userHandle) {
             // If this is the leaf node add the observer
             if (index == countUriSegments(uri)) {
-                mObservers.add(new ObserverEntry(observer, notifyForDescendents, observersLock,
-                        uid, pid));
+                mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
+                        uid, pid, userHandle));
                 return;
             }
 
@@ -662,8 +732,8 @@
             for (int i = 0; i < N; i++) {
                 ObserverNode node = mChildren.get(i);
                 if (node.mName.equals(segment)) {
-                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
-                            observersLock, uid, pid);
+                    node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+                            observersLock, uid, pid, userHandle);
                     return;
                 }
             }
@@ -671,8 +741,8 @@
             // No child found, create one
             ObserverNode node = new ObserverNode(segment);
             mChildren.add(node);
-            node.addObserverLocked(uri, index + 1, observer, notifyForDescendents,
-                    observersLock, uid, pid);
+            node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
+                    observersLock, uid, pid, userHandle);
         }
 
         public boolean removeObserverLocked(IContentObserver observer) {
@@ -705,37 +775,49 @@
         }
 
         private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
-                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+                boolean observerWantsSelfNotifications, int targetUserHandle,
+                ArrayList<ObserverCall> calls) {
             int N = mObservers.size();
             IBinder observerBinder = observer == null ? null : observer.asBinder();
             for (int i = 0; i < N; i++) {
                 ObserverEntry entry = mObservers.get(i);
 
-                // Don't notify the observer if it sent the notification and isn't interesed
+                // Don't notify the observer if it sent the notification and isn't interested
                 // in self notifications
                 boolean selfChange = (entry.observer.asBinder() == observerBinder);
                 if (selfChange && !observerWantsSelfNotifications) {
                     continue;
                 }
 
-                // Make sure the observer is interested in the notification
-                if (leaf || (!leaf && entry.notifyForDescendents)) {
-                    calls.add(new ObserverCall(this, entry.observer, selfChange));
+                // Does this observer match the target user?
+                if (targetUserHandle == UserHandle.USER_ALL
+                        || entry.userHandle == UserHandle.USER_ALL
+                        || targetUserHandle == entry.userHandle) {
+                    // Make sure the observer is interested in the notification
+                    if (leaf || (!leaf && entry.notifyForDescendants)) {
+                        calls.add(new ObserverCall(this, entry.observer, selfChange));
+                    }
                 }
             }
         }
 
+        /**
+         * targetUserHandle is either a hard user handle or is USER_ALL
+         */
         public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
-                boolean observerWantsSelfNotifications, ArrayList<ObserverCall> calls) {
+                boolean observerWantsSelfNotifications, int targetUserHandle,
+                ArrayList<ObserverCall> calls) {
             String segment = null;
             int segmentCount = countUriSegments(uri);
             if (index >= segmentCount) {
                 // This is the leaf node, notify all observers
-                collectMyObserversLocked(true, observer, observerWantsSelfNotifications, calls);
+                collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
+                        targetUserHandle, calls);
             } else if (index < segmentCount){
                 segment = getUriSegment(uri, index);
-                // Notify any observers at this level who are interested in descendents
-                collectMyObserversLocked(false, observer, observerWantsSelfNotifications, calls);
+                // Notify any observers at this level who are interested in descendants
+                collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
+                        targetUserHandle, calls);
             }
 
             int N = mChildren.size();
@@ -744,7 +826,7 @@
                 if (segment == null || node.mName.equals(segment)) {
                     // We found the child,
                     node.collectObserversLocked(uri, index + 1,
-                            observer, observerWantsSelfNotifications, calls);
+                            observer, observerWantsSelfNotifications, targetUserHandle, calls);
                     if (segment != null) {
                         break;
                     }
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/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 86a9392..f956bcf 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -30,12 +30,28 @@
  * @hide
  */
 interface IContentService {
-    void registerContentObserver(in Uri uri, boolean notifyForDescendentsn,
-            IContentObserver observer);
     void unregisterContentObserver(IContentObserver observer);
 
+    /**
+     * Register a content observer tied to a specific user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be observed.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and
+     *     USER_CURRENT are properly handled.
+     */
+    void registerContentObserver(in Uri uri, boolean notifyForDescendants,
+            IContentObserver observer, int userHandle);
+
+    /**
+     * Notify observers of a particular user's view of the provider.
+     * @param userHandle the user whose view of the provider is to be notified.  May be
+     *     the calling user without requiring any permission, otherwise the caller needs to
+     *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL
+     *     USER_CURRENT are properly interpreted.
+     */
     void notifyChange(in Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork);
+            boolean observerWantsSelfNotifications, boolean syncToNetwork,
+            int userHandle);
 
     void requestSync(in Account account, String authority, in Bundle extras);
     void cancelSync(in Account account, String authority);
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/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/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/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/content/ObserverNodeTest.java b/core/tests/coretests/src/android/content/ObserverNodeTest.java
index 95b8465..1acff9c 100644
--- a/core/tests/coretests/src/android/content/ObserverNodeTest.java
+++ b/core/tests/coretests/src/android/content/ObserverNodeTest.java
@@ -23,6 +23,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 
 public class ObserverNodeTest extends AndroidTestCase {
@@ -33,6 +34,8 @@
     }
 
     public void testUri() {
+        final int myUserHandle = UserHandle.myUserId();
+
         ObserverNode root = new ObserverNode("");
         Uri[] uris = new Uri[] {
             Uri.parse("content://c/a/"),
@@ -48,21 +51,25 @@
         int[] nums = new int[] {4, 7, 1, 4, 2, 2, 3, 3};
 
         // special case
-        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root, 0, 0);
+        root.addObserverLocked(uris[0], new TestObserver().getContentObserver(), false, root,
+                0, 0, myUserHandle);
         for(int i = 1; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root, 0, 0);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), true, root,
+                    0, 0, myUserHandle);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = nums.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
     }
 
     public void testUriNotNotify() {
+        final int myUserHandle = UserHandle.myUserId();
+
         ObserverNode root = new ObserverNode("");
         Uri[] uris = new Uri[] {
             Uri.parse("content://c/"),
@@ -77,13 +84,14 @@
         int[] nums = new int[] {7, 1, 3, 3, 1, 1, 1, 1};
 
         for(int i = 0; i < uris.length; i++) {
-            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root, 0, 0);
+            root.addObserverLocked(uris[i], new TestObserver().getContentObserver(), false, root,
+                    0, 0, myUserHandle);
         }
 
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = uris.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
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/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 7cc5dec..a0ae9e3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -317,13 +317,14 @@
 
         boolean backedUpDataChanged = false;
         String property = null, table = uri.getPathSegments().get(0);
+        final boolean isGlobal = table.equals(TABLE_GLOBAL);
         if (table.equals(TABLE_SYSTEM)) {
             property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
             backedUpDataChanged = true;
         } else if (table.equals(TABLE_SECURE)) {
             property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
             backedUpDataChanged = true;
-        } else if (table.equals(TABLE_GLOBAL)) {
+        } else if (isGlobal) {
             property = Settings.Global.SYS_PROP_SETTING_VERSION;    // this one is global
             backedUpDataChanged = true;
         }
@@ -342,8 +343,9 @@
 
         String notify = uri.getQueryParameter("notify");
         if (notify == null || "true".equals(notify)) {
-            getContext().getContentResolver().notifyChange(uri, null);
-            if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri);
+            final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
+            getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
+            if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
         } else {
             if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
         }
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/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/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/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index edd1dac..35dd764 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -137,18 +137,6 @@
     /* Idle time after a peer is gone when the group is torn down */
     private static final int GROUP_IDLE_TIME_S = 5;
 
-    /**
-     * Delay between restarts upon failure to setup connection with supplicant
-     */
-    private static final int P2P_RESTART_INTERVAL_MSECS = 5000;
-
-    /**
-     * Number of times we attempt to restart p2p
-     */
-    private static final int P2P_RESTART_TRIES = 5;
-
-    private int mP2pRestartCount = 0;
-
     private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
 
     /* Delayed message to timeout group creation */
@@ -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();
@@ -1597,6 +1588,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() {