Merge "Minor refactors." into jb-mr1-dev
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index e621ceb..36bf38a 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1120,8 +1120,8 @@
 
         ClearDataObserver obs = new ClearDataObserver();
         try {
-            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs,
-                    Binder.getOrigCallingUser())) {
+            // XXX TO DO: add user arg
+            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, 0)) {
                 System.err.println("Failed");
             }
 
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 7a9f285..9caf84f 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1052,7 +1052,7 @@
         if (account == null) throw new IllegalArgumentException("account is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
         checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
-        UserAccounts accounts = getUserAccountsForCaller();
+        final UserAccounts accounts = getUserAccountsForCaller();
         AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
             mAuthenticatorCache.getServiceInfo(
                     AuthenticatorDescription.newKey(account.type));
@@ -1141,7 +1141,7 @@
                         if (intent != null && notifyOnAuthFailure && !customTokens) {
                             doNotification(mAccounts,
                                     account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
-                                    intent);
+                                    intent, accounts.userId);
                         }
                     }
                     super.onResult(result);
@@ -1152,7 +1152,8 @@
         }
     }
 
-    private void createNoCredentialsPermissionNotification(Account account, Intent intent) {
+    private void createNoCredentialsPermissionNotification(Account account, Intent intent,
+            int userId) {
         int uid = intent.getIntExtra(
                 GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
         String authTokenType = intent.getStringExtra(
@@ -1172,9 +1173,10 @@
             title = titleAndSubtitle.substring(0, index);
             subtitle = titleAndSubtitle.substring(index + 1);            
         }
-        n.setLatestEventInfo(mContext,
-                title, subtitle,
-                PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
+        n.setLatestEventInfo(mContext, title, subtitle,
+                PendingIntent.getActivityAsUser(mContext, 0, intent,
+                        PendingIntent.FLAG_CANCEL_CURRENT,
+                        null, new UserHandle(userId)));
         installNotification(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
     }
 
@@ -1879,7 +1881,7 @@
 
     private static String getDatabaseName(int userId) {
         File systemDir = Environment.getSystemSecureDirectory();
-        File databaseFile = new File(systemDir, "users/" + userId + "/" + DATABASE_NAME);
+        File databaseFile = new File(Environment.getUserSystemDirectory(userId), DATABASE_NAME);
         if (userId == 0) {
             // Migrate old file, if it exists, to the new location.
             // Make sure the new file doesn't already exist. A dummy file could have been
@@ -1888,7 +1890,7 @@
             File oldFile = new File(systemDir, DATABASE_NAME);
             if (oldFile.exists() && !databaseFile.exists()) {
                 // Check for use directory; create if it doesn't exist, else renameTo will fail
-                File userDir = new File(systemDir, "users/" + userId);
+                File userDir = Environment.getUserSystemDirectory(userId);
                 if (!userDir.exists()) {
                     if (!userDir.mkdirs()) {
                         throw new IllegalStateException("User dir cannot be created: " + userDir);
@@ -2083,7 +2085,7 @@
     }
 
     private void doNotification(UserAccounts accounts, Account account, CharSequence message,
-            Intent intent) {
+            Intent intent, int userId) {
         long identityToken = clearCallingIdentity();
         try {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -2093,7 +2095,7 @@
             if (intent.getComponent() != null &&
                     GrantCredentialsPermissionActivity.class.getName().equals(
                             intent.getComponent().getClassName())) {
-                createNoCredentialsPermissionNotification(account, intent);
+                createNoCredentialsPermissionNotification(account, intent, userId);
             } else {
                 final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
                 intent.addCategory(String.valueOf(notificationId));
@@ -2103,8 +2105,9 @@
                         mContext.getText(R.string.notification_title).toString();
                 n.setLatestEventInfo(mContext,
                         String.format(notificationTitleFormat, account.name),
-                        message, PendingIntent.getActivity(
-                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
+                        message, PendingIntent.getActivityAsUser(
+                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+                        null, new UserHandle(userId)));
                 installNotification(notificationId, n);
             }
         } finally {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d5580b7..99dfccb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4278,7 +4278,8 @@
                 ActivityManagerNative.getDefault().getIntentSender(
                         ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
                         mParent == null ? mToken : mParent.mToken,
-                        mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null);
+                        mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null,
+                        UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
             // Empty
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 26d8c17..cd22aad 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -27,6 +27,7 @@
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Point;
@@ -1225,7 +1226,7 @@
     public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
         try {
             return ActivityManagerNative.getDefault().clearApplicationUserData(packageName, 
-                    observer, Binder.getOrigCallingUser());
+                    observer, UserHandle.myUserId());
         } catch (RemoteException e) {
             return false;
         }
@@ -1902,6 +1903,31 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
+    /** @hide */
+    public static int handleIncomingUser(int callingPid, int callingUid, int userId,
+            boolean allowAll, boolean requireFull, String name, String callerPackage) {
+        if (UserHandle.getUserId(callingUid) == userId) {
+            return userId;
+        }
+        try {
+            return ActivityManagerNative.getDefault().handleIncomingUser(callingPid,
+                    callingUid, userId, allowAll, requireFull, name, callerPackage);
+        } catch (RemoteException e) {
+            throw new SecurityException("Failed calling activity manager", e);
+        }
+    }
+
+    /** @hide */
+    public static int getCurrentUser() {
+        UserInfo ui;
+        try {
+            ui = ActivityManagerNative.getDefault().getCurrentUser();
+            return ui != null ? ui.id : 0;
+        } catch (RemoteException e) {
+            return 0;
+        }
+    }
+
     /**
      * Returns the usage statistics of each installed package.
      *
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 16b7c2a..14ba537 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -199,8 +199,9 @@
             Configuration config = Configuration.CREATOR.createFromParcel(data);
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             int result = startActivityWithConfig(app, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, config, options);
+                    resultTo, resultWho, requestCode, startFlags, config, options, userId);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -897,9 +898,10 @@
             int fl = data.readInt();
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             IIntentSender res = getIntentSender(type, packageName, token,
                     resultWho, requestCode, requestIntents,
-                    requestResolvedTypes, fl, options);
+                    requestResolvedTypes, fl, options, userId);
             reply.writeNoException();
             reply.writeStrongBinder(res != null ? res.asBinder() : null);
             return true;
@@ -934,6 +936,22 @@
             return true;
         }
 
+        case HANDLE_INCOMING_USER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int callingPid = data.readInt();
+            int callingUid = data.readInt();
+            int userId = data.readInt();
+            boolean allowAll = data.readInt() != 0 ;
+            boolean requireFull = data.readInt() != 0;
+            String name = data.readString();
+            String callerPackage = data.readString();
+            int res = handleIncomingUser(callingPid, callingUid, userId, allowAll,
+                    requireFull, name, callerPackage);
+            reply.writeNoException();
+            reply.writeInt(res);
+            return true;
+        }
+
         case SET_PROCESS_LIMIT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int max = data.readInt();
@@ -1304,25 +1322,6 @@
             return true;
         }
         
-        case START_ACTIVITY_IN_PACKAGE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
-            Intent intent = Intent.CREATOR.createFromParcel(data);
-            String resolvedType = data.readString();
-            IBinder resultTo = data.readStrongBinder();
-            String resultWho = data.readString();    
-            int requestCode = data.readInt();
-            int startFlags = data.readInt();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivityInPackage(uid, intent, resolvedType,
-                    resultTo, resultWho, requestCode, startFlags, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-        
         case KILL_APPLICATION_WITH_UID_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
@@ -1489,22 +1488,6 @@
             return true;
         }
 
-        case START_ACTIVITIES_IN_PACKAGE_TRANSACTION:
-        {
-            data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
-            Intent[] intents = data.createTypedArray(Intent.CREATOR);
-            String[] resolvedTypes = data.createStringArray();
-            IBinder resultTo = data.readStrongBinder();
-            Bundle options = data.readInt() != 0
-                    ? Bundle.CREATOR.createFromParcel(data) : null;
-            int result = startActivitiesInPackage(uid, intents, resolvedTypes,
-                    resultTo, options);
-            reply.writeNoException();
-            reply.writeInt(result);
-            return true;
-        }
-
         case START_ACTIVITIES_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -1877,7 +1860,7 @@
     public int startActivityWithConfig(IApplicationThread caller, Intent intent,
             String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int startFlags, Configuration config,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -1895,6 +1878,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
@@ -2840,7 +2824,7 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -2863,6 +2847,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0);
         reply.readException();
         IIntentSender res = IIntentSender.Stub.asInterface(
@@ -2905,6 +2890,25 @@
         reply.recycle();
         return res;
     }
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(callingPid);
+        data.writeInt(callingUid);
+        data.writeInt(userId);
+        data.writeInt(allowAll ? 1 : 0);
+        data.writeInt(requireFull ? 1 : 0);
+        data.writeString(name);
+        data.writeString(callerPackage);
+        mRemote.transact(HANDLE_INCOMING_USER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
     public void setProcessLimit(int max) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -3360,34 +3364,6 @@
         data.recycle();
     }
     
-    public int startActivityInPackage(int uid,
-            Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options)
-            throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        intent.writeToParcel(data, 0);
-        data.writeString(resolvedType);
-        data.writeStrongBinder(resultTo);
-        data.writeString(resultWho);
-        data.writeInt(requestCode);
-        data.writeInt(startFlags);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITY_IN_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-    
     public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -3655,30 +3631,6 @@
         return result;
     }
 
-    public int startActivitiesInPackage(int uid,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
-        data.writeTypedArray(intents, 0);
-        data.writeStringArray(resolvedTypes);
-        data.writeStrongBinder(resultTo);
-        if (options != null) {
-            data.writeInt(1);
-            options.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
-        mRemote.transact(START_ACTIVITIES_IN_PACKAGE_TRANSACTION, data, reply, 0);
-        reply.readException();
-        int result = reply.readInt();
-        reply.recycle();
-        data.recycle();
-        return result;
-    }
-
     public int getFrontActivityScreenCompatMode() throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ea77bcd..232ca07 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1000,7 +1000,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, false, false,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1013,7 +1013,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, false, false,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1027,7 +1027,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, receiverPermission, true, false,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1060,7 +1060,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermission,
-                true, false, Binder.getOrigCallingUser());
+                true, false, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1131,7 +1131,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, false, true,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1164,7 +1164,7 @@
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, null,
-                true, true, Binder.getOrigCallingUser());
+                true, true, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
@@ -1179,7 +1179,7 @@
         try {
             intent.setAllowFds(false);
             ActivityManagerNative.getDefault().unbroadcastIntent(
-                    mMainThread.getApplicationThread(), intent, Binder.getOrigCallingUser());
+                    mMainThread.getApplicationThread(), intent, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 70d8445..f7c7013 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -66,7 +66,7 @@
     public int startActivityWithConfig(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho,
             int requestCode, int startFlags, Configuration newConfig,
-            Bundle options) throws RemoteException;
+            Bundle options, int userId) throws RemoteException;
     public int startActivityIntentSender(IApplicationThread caller,
             IntentSender intent, Intent fillInIntent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode,
@@ -177,13 +177,16 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes,
-            int flags, Bundle options) throws RemoteException;
+            int flags, Bundle options, int userId) throws RemoteException;
     public void cancelIntentSender(IIntentSender sender) throws RemoteException;
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) throws RemoteException;
     public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
     public int getUidForIntentSender(IIntentSender sender) throws RemoteException;
     
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) throws RemoteException;
+
     public void setProcessLimit(int max) throws RemoteException;
     public int getProcessLimit() throws RemoteException;
     
@@ -272,11 +275,6 @@
     public void stopAppSwitches() throws RemoteException;
     public void resumeAppSwitches() throws RemoteException;
     
-    public int startActivityInPackage(int uid,
-            Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options)
-            throws RemoteException;
-
     public void killApplicationWithUid(String pkg, int uid) throws RemoteException;
     
     public void closeSystemDialogs(String reason) throws RemoteException;
@@ -316,9 +314,6 @@
     public int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
             Bundle options) throws RemoteException;
-    public int startActivitiesInPackage(int uid,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException;
 
     public int getFrontActivityScreenCompatMode() throws RemoteException;
     public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
@@ -551,9 +546,8 @@
     int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
     int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
     int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
+    int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
 
-
-    int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
     int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
     int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
@@ -580,7 +574,7 @@
     int CHECK_GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+118;
     int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
     int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
-    int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
+
     int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
     int GET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
     int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 6f95e26..62d4962 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -24,16 +24,13 @@
 /** {@hide} */
 interface INotificationManager
 {
-    /** @deprecated use {@link #enqueueNotificationWithTag} instead */
-    void enqueueNotification(String pkg, int id, in Notification notification, inout int[] idReceived);
-    /** @deprecated use {@link #cancelNotificationWithTag} instead */
-    void cancelNotification(String pkg, int id);
-    void cancelAllNotifications(String pkg);
+    void cancelAllNotifications(String pkg, int userId);
 
     void enqueueToast(String pkg, ITransientNotification callback, int duration);
     void cancelToast(String pkg, ITransientNotification callback);
-    void enqueueNotificationWithTag(String pkg, String tag, int id, in Notification notification, inout int[] idReceived);
-    void cancelNotificationWithTag(String pkg, String tag, int id);
+    void enqueueNotificationWithTag(String pkg, String tag, int id,
+            in Notification notification, inout int[] idReceived, int userId);
+    void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
 
     void setNotificationsEnabledForPackage(String pkg, boolean enabled);
     boolean areNotificationsEnabledForPackage(String pkg);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 69c20b0..c095280 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Log;
 
 /**
@@ -125,7 +126,27 @@
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
         try {
-            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);
+            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut,
+                    UserHandle.myUserId());
+            if (id != idOut[0]) {
+                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
+    {
+        int[] idOut = new int[1];
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
+        try {
+            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut,
+                    user.getIdentifier());
             if (id != idOut[0]) {
                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
             }
@@ -154,7 +175,21 @@
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
         try {
-            service.cancelNotificationWithTag(pkg, tag, id);
+            service.cancelNotificationWithTag(pkg, tag, id, UserHandle.myUserId());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void cancelAsUser(String tag, int id, UserHandle user)
+    {
+        INotificationManager service = getService();
+        String pkg = mContext.getPackageName();
+        if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
+        try {
+            service.cancelNotificationWithTag(pkg, tag, id, user.getIdentifier());
         } catch (RemoteException e) {
         }
     }
@@ -169,7 +204,7 @@
         String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
         try {
-            service.cancelAllNotifications(pkg);
+            service.cancelAllNotifications(pkg, UserHandle.myUserId());
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index a57c516..bcd42ea 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -228,7 +228,29 @@
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, options);
+                    flags, options, UserHandle.myUserId());
+            return target != null ? new PendingIntent(target) : null;
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    public static PendingIntent getActivityAsUser(Context context, int requestCode,
+            Intent intent, int flags, Bundle options, UserHandle user) {
+        String packageName = context.getPackageName();
+        String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
+                context.getContentResolver()) : null;
+        try {
+            intent.setAllowFds(false);
+            IIntentSender target =
+                ActivityManagerNative.getDefault().getIntentSender(
+                    ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+                    null, null, requestCode, new Intent[] { intent },
+                    resolvedType != null ? new String[] { resolvedType } : null,
+                    flags, options, user.getIdentifier());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -334,7 +356,8 @@
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
-                    null, null, requestCode, intents, resolvedTypes, flags, options);
+                    null, null, requestCode, intents, resolvedTypes, flags, options,
+                    UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -372,7 +395,7 @@
                     ActivityManager.INTENT_SENDER_BROADCAST, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, null);
+                    flags, null, UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
@@ -411,7 +434,7 @@
                     ActivityManager.INTENT_SENDER_SERVICE, packageName,
                     null, null, requestCode, new Intent[] { intent },
                     resolvedType != null ? new String[] { resolvedType } : null,
-                    flags, null);
+                    flags, null, UserHandle.myUserId());
             return target != null ? new PendingIntent(target) : null;
         } catch (RemoteException e) {
         }
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index a74a268..9e8ab2c 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -20,7 +20,9 @@
 import android.content.Context;
 import android.graphics.BitmapFactory;
 import android.graphics.Point;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.view.Display;
 import android.view.WindowManager;
@@ -39,8 +41,12 @@
 
     // This path must match what the WallpaperManagerService uses
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    public static final String WALLPAPER_IMAGE = "/data/system/users/0/wallpaper";
-    public static final String WALLPAPER_INFO = "/data/system/users/0/wallpaper_info.xml";
+    public static final String WALLPAPER_IMAGE =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper").getAbsolutePath();
+    public static final String WALLPAPER_INFO =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper_info.xml").getAbsolutePath();
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     public static final String WALLPAPER_IMAGE_KEY =
             "/data/data/com.android.settings/files/wallpaper";
@@ -50,7 +56,9 @@
     // will be saved to this file from the restore stream, then renamed to the proper
     // location if it's deemed suitable.
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String STAGE_FILE = "/data/system/users/0/wallpaper-tmp";
+    private static final String STAGE_FILE =
+            new File(Environment.getUserSystemDirectory(UserHandle.USER_OWNER),
+                    "wallpaper-tmp").getAbsolutePath();
 
     Context mContext;
     String[] mFiles;
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index ee075b4..6b5e6e2 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -980,7 +980,7 @@
             mSyncHandler.sendMessage(msg);
         }
 
-        boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info) {
+        boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
             }
@@ -989,8 +989,9 @@
             intent.setComponent(info.componentName);
             intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                     com.android.internal.R.string.sync_binding_label);
-            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
-                    mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
+                    mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
+                    null, new UserHandle(userId)));
             mBound = true;
             final boolean bindResult = mContext.bindService(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
@@ -2132,7 +2133,7 @@
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
             }
-            if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo)) {
+            if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
                 Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
                 closeActiveSyncContext(activeSyncContext);
                 return false;
@@ -2255,10 +2256,12 @@
 
             if (syncResult != null && syncResult.tooManyDeletions) {
                 installHandleTooManyDeletesNotification(syncOperation.account,
-                        syncOperation.authority, syncResult.stats.numDeletes);
+                        syncOperation.authority, syncResult.stats.numDeletes,
+                        syncOperation.userId);
             } else {
-                mNotificationMgr.cancel(
-                        syncOperation.account.hashCode() ^ syncOperation.authority.hashCode());
+                mNotificationMgr.cancelAsUser(null,
+                        syncOperation.account.hashCode() ^ syncOperation.authority.hashCode(),
+                        new UserHandle(syncOperation.userId));
             }
 
             if (syncResult != null && syncResult.fullSyncRequested) {
@@ -2471,7 +2474,7 @@
         }
 
         private void installHandleTooManyDeletesNotification(Account account, String authority,
-                long numDeletes) {
+                long numDeletes, int userId) {
             if (mNotificationMgr == null) return;
 
             final ProviderInfo providerInfo = mContext.getPackageManager().resolveContentProvider(
@@ -2493,7 +2496,8 @@
             }
 
             final PendingIntent pendingIntent = PendingIntent
-                    .getActivity(mContext, 0, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+                    .getActivityAsUser(mContext, 0, clickIntent,
+                            PendingIntent.FLAG_CANCEL_CURRENT, null, new UserHandle(userId));
 
             CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
                     R.string.contentServiceTooManyDeletesNotificationDesc);
@@ -2507,7 +2511,8 @@
                     String.format(tooManyDeletesDescFormat.toString(), authorityName),
                     pendingIntent);
             notification.flags |= Notification.FLAG_ONGOING_EVENT;
-            mNotificationMgr.notify(account.hashCode() ^ authority.hashCode(), notification);
+            mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
+                    notification, new UserHandle(userId));
         }
 
         /**
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 5d40456..ea14098 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -73,34 +73,6 @@
     public static final native int getCallingUid();
 
     /**
-     * Return the original ID of the user assigned to the process that sent you the current
-     * transaction that is being processed. This uid can be used with higher-level system services
-     * to determine its identity and check permissions. If the current thread is not currently
-     * executing an incoming transaction, then its own uid is returned.
-     * <p/>
-     * This value cannot be reset by calls to {@link #clearCallingIdentity()}.
-     * @hide
-     */
-    public static final int getOrigCallingUid() {
-        if (UserHandle.MU_ENABLED) {
-            return getOrigCallingUidNative();
-        } else {
-            return getCallingUid();
-        }
-    }
-
-    private static final native int getOrigCallingUidNative();
-
-    /**
-     * Utility function to return the user id of the calling process.
-     * @return userId of the calling process, extracted from the callingUid
-     * @hide
-     */
-    public static final int getOrigCallingUser() {
-        return UserHandle.getUserId(getOrigCallingUid());
-    }
-
-    /**
      * Reset the identity of the incoming IPC on the current thread.  This can
      * be useful if, while handling an incoming call, you will be calling
      * on interfaces of other objects that may be local to your process and
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 679cf1a..2fbcf3f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -104,6 +104,17 @@
     }
 
     /**
+     * Return the system directory for a user. This is for use by system services to store
+     * files relating to the user. This directory will be automatically deleted when the user
+     * is removed.
+     *
+     * @hide
+     */
+    public static File getUserSystemDirectory(int userId) {
+        return new File(new File(getSystemSecureDirectory(), "users"), Integer.toString(userId));
+    }
+
+    /**
      * Returns whether the Encrypted File System feature is enabled on the device or not.
      * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
      * if disabled.
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
index 350e006..4ecbd16 100644
--- a/core/java/com/android/internal/widget/LockSettingsService.java
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -23,6 +23,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Binder;
+import android.os.Environment;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -173,7 +174,8 @@
             // Leave it in the same place for user 0
             return dataSystemDirectory + LOCK_PATTERN_FILE;
         } else {
-            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PATTERN_FILE;
+            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
+                    .getAbsolutePath();
         }
     }
 
@@ -185,7 +187,8 @@
             // Leave it in the same place for user 0
             return dataSystemDirectory + LOCK_PASSWORD_FILE;
         } else {
-            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PASSWORD_FILE;
+            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
+                    .getAbsolutePath();
         }
     }
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 04dc49f..881d9a0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -729,11 +729,6 @@
     return IPCThreadState::self()->getCallingUid();
 }
 
-static jint android_os_Binder_getOrigCallingUid(JNIEnv* env, jobject clazz)
-{
-    return IPCThreadState::self()->getOrigCallingUid();
-}
-
 static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
 {
     return IPCThreadState::self()->clearCallingIdentity();
@@ -805,7 +800,6 @@
      /* name, signature, funcPtr */
     { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid },
     { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
-    { "getOrigCallingUidNative", "()I", (void*)android_os_Binder_getOrigCallingUid },
     { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
     { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
     { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 9fc73a4..3538fef 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -46,6 +46,7 @@
 #include <OpenGLRenderer.h>
 #include <SkiaShader.h>
 #include <SkiaColorFilter.h>
+#include <Stencil.h>
 #include <Rect.h>
 
 #include <TextLayout.h>
@@ -150,7 +151,7 @@
 }
 
 static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
-    return OpenGLRenderer::getStencilSize();
+    return Stencil::getStencilSize();
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
index 7f551b0..f28ba7e 100644
--- a/core/tests/coretests/src/android/app/activity/BroadcastTest.java
+++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
@@ -305,7 +305,7 @@
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
         ActivityManagerNative.getDefault().unbroadcastIntent(null, intent,
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
 
         ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.myUserId());
         addIntermediate("finished-broadcast");
@@ -323,7 +323,7 @@
 
         ActivityManagerNative.getDefault().unbroadcastIntent(
                 null, new Intent(LaunchpadActivity.BROADCAST_STICKY1, null),
-                Binder.getOrigCallingUser());
+                UserHandle.myUserId());
         addIntermediate("finished-unbroadcast");
 
         IntentFilter filter = new IntentFilter(LaunchpadActivity.BROADCAST_STICKY1);
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index 7b6e540..aabfcae 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -90,6 +90,10 @@
 
     @Override
     public Certificate[] engineGetCertificateChain(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
         final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
         if (leaf == null) {
             return null;
@@ -119,6 +123,10 @@
 
     @Override
     public Certificate engineGetCertificate(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
         byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
         if (certificate != null) {
             return toCertificate(certificate);
@@ -166,6 +174,10 @@
 
     @Override
     public Date engineGetCreationDate(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
         Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
         if (d != null) {
             return d;
@@ -325,7 +337,7 @@
     @Override
     public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
             throws KeyStoreException {
-        throw new RuntimeException("Operation not supported because key encoding is unknown");
+        throw new KeyStoreException("Operation not supported because key encoding is unknown");
     }
 
     @Override
@@ -334,6 +346,11 @@
             throw new KeyStoreException("Entry exists and is not a trusted certificate");
         }
 
+        // We can't set something to null.
+        if (cert == null) {
+            throw new NullPointerException("cert == null");
+        }
+
         final byte[] encoded;
         try {
             encoded = cert.getEncoded();
@@ -348,6 +365,10 @@
 
     @Override
     public void engineDeleteEntry(String alias) throws KeyStoreException {
+        if (!isKeyEntry(alias) && !isCertificateEntry(alias)) {
+            return;
+        }
+
         if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias)) {
             throw new KeyStoreException("No such entry " + alias);
         }
@@ -380,6 +401,10 @@
 
     @Override
     public boolean engineContainsAlias(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
         return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
                 || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
                 || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
@@ -396,12 +421,24 @@
     }
 
     private boolean isKeyEntry(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
         return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
     }
 
+    private boolean isCertificateEntry(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        return mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+    }
+
     @Override
     public boolean engineIsCertificateEntry(String alias) {
-        return !isKeyEntry(alias) && mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
+        return !isKeyEntry(alias) && isCertificateEntry(alias);
     }
 
     @Override
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 1947c32..c3a07a1 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -28,6 +28,7 @@
 		SkiaColorFilter.cpp \
 		SkiaShader.cpp \
 		Snapshot.cpp \
+		Stencil.cpp \
 		TextureCache.cpp \
 		TextDropShadowCache.cpp
 	
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index f4f56d6..b9a6336 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -38,6 +38,7 @@
 #include "TextDropShadowCache.h"
 #include "FboCache.h"
 #include "ResourceCache.h"
+#include "Stencil.h"
 #include "Dither.h"
 
 namespace android {
@@ -252,10 +253,14 @@
     TextDropShadowCache dropShadowCache;
     FboCache fboCache;
     ResourceCache resourceCache;
-    Dither dither;
 
     GammaFontRenderer* fontRenderer;
 
+    Dither dither;
+#if STENCIL_BUFFER_SIZE
+    Stencil stencil;
+#endif
+
     // Debug methods
     PFNGLINSERTEVENTMARKEREXTPROC eventMark;
     PFNGLPUSHGROUPMARKEREXTPROC startMark;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8da9f66..2f43be8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -139,10 +139,6 @@
 // Setup
 ///////////////////////////////////////////////////////////////////////////////
 
-uint32_t OpenGLRenderer::getStencilSize() {
-    return STENCIL_BUFFER_SIZE;
-}
-
 bool OpenGLRenderer::isDeferred() {
     return false;
 }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2369f47..4c7cf0a 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -208,12 +208,6 @@
     SkPaint* filterPaint(SkPaint* paint);
 
     /**
-     * Returns the desired size for the stencil buffer. If the returned value
-     * is 0, then no stencil buffer is required.
-     */
-    ANDROID_API static uint32_t getStencilSize();
-
-    /**
      * Sets the alpha on the current snapshot. This alpha value will be modulated
      * with other alpha values when drawing primitives.
      */
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 5d5961a..4484676 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -57,7 +57,7 @@
         clipRect = &mClipRectRoot;
 #if STENCIL_BUFFER_SIZE
         if (s->clipRegion) {
-            mClipRegionRoot.merge(*s->clipRegion);
+            mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
             clipRegion = &mClipRegionRoot;
         }
 #endif
@@ -84,8 +84,7 @@
 #if STENCIL_BUFFER_SIZE
     if (!clipRegion) {
         clipRegion = &mClipRegionRoot;
-        android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
-        clipRegion->set(tmp);
+        clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
     }
 #endif
 }
@@ -93,11 +92,11 @@
 void Snapshot::copyClipRectFromRegion() {
 #if STENCIL_BUFFER_SIZE
     if (!clipRegion->isEmpty()) {
-        android::Rect bounds(clipRegion->bounds());
-        clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);
+        const SkIRect& bounds = clipRegion->getBounds();
+        clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
 
         if (clipRegion->isRect()) {
-            clipRegion->clear();
+            clipRegion->setEmpty();
             clipRegion = NULL;
         }
     } else {
@@ -107,43 +106,11 @@
 #endif
 }
 
-bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
+bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
 #if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->orSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->xorSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->andSelf(tmp);
-    copyClipRectFromRegion();
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
-#if STENCIL_BUFFER_SIZE
-    android::Rect tmp(left, top, right, bottom);
-    clipRegion->subtractSelf(tmp);
+    SkIRect tmp;
+    tmp.set(left, top, right, bottom);
+    clipRegion->op(tmp, op);
     copyClipRectFromRegion();
     return true;
 #else
@@ -161,14 +128,9 @@
     bool clipped = false;
 
     switch (op) {
-        case SkRegion::kDifference_Op: {
-            ensureClipRegion();
-            clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
-            break;
-        }
         case SkRegion::kIntersect_Op: {
             if (CC_UNLIKELY(clipRegion)) {
-                clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
+                clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
             } else {
                 clipped = clipRect->intersect(r);
                 if (!clipped) {
@@ -180,26 +142,22 @@
         }
         case SkRegion::kUnion_Op: {
             if (CC_UNLIKELY(clipRegion)) {
-                clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
+                clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
             } else {
                 clipped = clipRect->unionWith(r);
             }
             break;
         }
-        case SkRegion::kXOR_Op: {
-            ensureClipRegion();
-            clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
-            break;
-        }
-        case SkRegion::kReverseDifference_Op: {
-            // TODO!!!!!!!
-            break;
-        }
         case SkRegion::kReplace_Op: {
             setClip(r.left, r.top, r.right, r.bottom);
             clipped = true;
             break;
         }
+        default: {
+            ensureClipRegion();
+            clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
+            break;
+        }
     }
 
     if (clipped) {
@@ -213,7 +171,7 @@
     clipRect->set(left, top, right, bottom);
 #if STENCIL_BUFFER_SIZE
     if (clipRegion) {
-        clipRegion->clear();
+        clipRegion->setEmpty();
         clipRegion = NULL;
     }
 #endif
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 30b03fc..a89b740 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -198,7 +198,7 @@
      *
      * This field is used only if STENCIL_BUFFER_SIZE is > 0.
      */
-    Region* clipRegion;
+    SkRegion* clipRegion;
 
     /**
      * The ancestor layer's dirty region.
@@ -223,17 +223,14 @@
     void ensureClipRegion();
     void copyClipRectFromRegion();
 
-    bool clipRegionOr(float left, float top, float right, float bottom);
-    bool clipRegionXor(float left, float top, float right, float bottom);
-    bool clipRegionAnd(float left, float top, float right, float bottom);
-    bool clipRegionNand(float left, float top, float right, float bottom);
+    bool clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op);
 
     mat4 mTransformRoot;
     Rect mClipRectRoot;
     Rect mLocalClip;
 
 #if STENCIL_BUFFER_SIZE
-    Region mClipRegionRoot;
+    SkRegion mClipRegionRoot;
 #endif
 
 }; // class Snapshot
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
new file mode 100644
index 0000000..9d2c86f
--- /dev/null
+++ b/libs/hwui/Stencil.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#include <GLES2/gl2.h>
+
+#include "Properties.h"
+#include "Stencil.h"
+
+namespace android {
+namespace uirenderer {
+
+Stencil::Stencil(): mState(kDisabled) {
+}
+
+uint32_t Stencil::getStencilSize() {
+    return STENCIL_BUFFER_SIZE;
+}
+
+void Stencil::clear() {
+    glClearStencil(0);
+    glClear(GL_STENCIL_BUFFER_BIT);
+}
+
+void Stencil::enableTest() {
+    if (mState != kTest) {
+        enable();
+        glStencilFunc(GL_LESS, 0x0, 0x1);
+        // We only want to test, let's keep everything
+        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+        mState = kTest;
+    }
+}
+
+void Stencil::enableWrite() {
+    if (mState != kWrite) {
+        enable();
+        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
+        // The test always passes so the first two values are meaningless
+        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+        mState = kWrite;
+    }
+}
+
+void Stencil::enable() {
+    if (!mState == kDisabled) {
+        glEnable(GL_STENCIL_TEST);
+    }
+}
+
+void Stencil::disable() {
+    if (mState != kDisabled) {
+        glDisable(GL_STENCIL_TEST);
+        mState = kDisabled;
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Stencil.h b/libs/hwui/Stencil.h
new file mode 100644
index 0000000..67ccc78
--- /dev/null
+++ b/libs/hwui/Stencil.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_STENCIL_H
+#define ANDROID_HWUI_STENCIL_H
+
+#ifndef LOG_TAG
+    #define LOG_TAG "OpenGLRenderer"
+#endif
+
+#include <cutils/compiler.h>
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stencil buffer management
+///////////////////////////////////////////////////////////////////////////////
+
+class ANDROID_API Stencil {
+public:
+    Stencil();
+
+    /**
+     * Returns the desired size for the stencil buffer. If the returned value
+     * is 0, then no stencil buffer is required.
+     */
+    ANDROID_API static uint32_t getStencilSize();
+
+    /**
+     * Clears the stencil buffer.
+     */
+    void clear();
+
+    /**
+     * Enables stencil test. When the stencil test is enabled the stencil
+     * buffer is not written into.
+     */
+    void enableTest();
+
+    /**
+     * Enables stencil write. When stencil write is enabled, the stencil
+     * test always succeeds and the value 0x1 is written in the stencil
+     * buffer for each fragment.
+     */
+    void enableWrite();
+
+    /**
+     * Disables stencil test and write.
+     */
+    void disable();
+
+    /**
+     * Indicates whether either test or write is enabled.
+     */
+    bool isEnabled() {
+        return mState != kDisabled;
+    }
+
+private:
+    void enable();
+
+    enum StencilState {
+        kDisabled,
+        kTest,
+        kWrite
+    };
+
+    StencilState mState;
+
+}; // class Stencil
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_STENCIL_H
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index a60bba7..bec5d72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.location.LocationManager;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.view.View;
@@ -84,10 +85,12 @@
         }
         
         try {
+            // XXX WHAT TO DO ABOUT MULTI-USER?
             if (visible) {
                 Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                 gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, gpsIntent, 0);
+                PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
+                        gpsIntent, 0, null, UserHandle.CURRENT);
 
                 Notification n = new Notification.Builder(mContext)
                     .setSmallIcon(iconId)
@@ -108,11 +111,12 @@
                         null, 
                         GPS_NOTIFICATION_ID, 
                         n,
-                        idOut);
+                        idOut,
+                        UserHandle.USER_CURRENT);
             } else {
-                mNotificationService.cancelNotification(
-                        mContext.getPackageName(),
-                        GPS_NOTIFICATION_ID);
+                mNotificationService.cancelNotificationWithTag(
+                        mContext.getPackageName(), null,
+                        GPS_NOTIFICATION_ID, UserHandle.USER_CURRENT);
             }
         } catch (android.os.RemoteException ex) {
             // well, it was worth a shot
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 8e341df..b869abd 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -31,6 +31,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -184,56 +185,62 @@
 
     @Override
     public int allocateAppWidgetId(String packageName, int hostId) throws RemoteException {
-        return getImplForUser().allocateAppWidgetId(packageName, hostId);
+        return getImplForUser(UserHandle.getCallingUserId()).allocateAppWidgetId(
+                packageName, hostId);
     }
     
     @Override
     public void deleteAppWidgetId(int appWidgetId) throws RemoteException {
-        getImplForUser().deleteAppWidgetId(appWidgetId);
+        getImplForUser(UserHandle.getCallingUserId()).deleteAppWidgetId(appWidgetId);
     }
 
     @Override
     public void deleteHost(int hostId) throws RemoteException {
-        getImplForUser().deleteHost(hostId);
+        getImplForUser(UserHandle.getCallingUserId()).deleteHost(hostId);
     }
 
     @Override
     public void deleteAllHosts() throws RemoteException {
-        getImplForUser().deleteAllHosts();
+        getImplForUser(UserHandle.getCallingUserId()).deleteAllHosts();
     }
 
     @Override
     public void bindAppWidgetId(int appWidgetId, ComponentName provider) throws RemoteException {
-        getImplForUser().bindAppWidgetId(appWidgetId, provider);
+        getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetId(appWidgetId, provider);
     }
 
     @Override
     public boolean bindAppWidgetIdIfAllowed(
             String packageName, int appWidgetId, ComponentName provider) throws RemoteException {
-        return getImplForUser().bindAppWidgetIdIfAllowed(packageName, appWidgetId, provider);
+        return getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetIdIfAllowed(
+                packageName, appWidgetId, provider);
     }
 
     @Override
     public boolean hasBindAppWidgetPermission(String packageName) throws RemoteException {
-        return getImplForUser().hasBindAppWidgetPermission(packageName);
+        return getImplForUser(UserHandle.getCallingUserId()).hasBindAppWidgetPermission(
+                packageName);
     }
 
     @Override
     public void setBindAppWidgetPermission(String packageName, boolean permission)
             throws RemoteException {
-        getImplForUser().setBindAppWidgetPermission(packageName, permission);
+        getImplForUser(UserHandle.getCallingUserId()).setBindAppWidgetPermission(
+                packageName, permission);
     }
 
     @Override
     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection)
             throws RemoteException {
-        getImplForUser().bindRemoteViewsService(appWidgetId, intent, connection);
+        getImplForUser(UserHandle.getCallingUserId()).bindRemoteViewsService(
+                appWidgetId, intent, connection);
     }
 
     @Override
     public int[] startListening(IAppWidgetHost host, String packageName, int hostId,
             List<RemoteViews> updatedViews) throws RemoteException {
-        return getImplForUser().startListening(host, packageName, hostId, updatedViews);
+        return getImplForUser(UserHandle.getCallingUserId()).startListening(host,
+                packageName, hostId, updatedViews);
     }
 
     public void onUserRemoved(int userId) {
@@ -247,8 +254,7 @@
         }
     }
 
-    private AppWidgetServiceImpl getImplForUser() {
-        final int userId = Binder.getOrigCallingUser();
+    private AppWidgetServiceImpl getImplForUser(int userId) {
         AppWidgetServiceImpl service = mAppWidgetServices.get(userId);
         if (service == null) {
             Slog.e(TAG, "Unable to find AppWidgetServiceImpl for the current user");
@@ -265,27 +271,27 @@
 
     @Override
     public int[] getAppWidgetIds(ComponentName provider) throws RemoteException {
-        return getImplForUser().getAppWidgetIds(provider);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetIds(provider);
     }
 
     @Override
     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetInfo(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetInfo(appWidgetId);
     }
 
     @Override
     public RemoteViews getAppWidgetViews(int appWidgetId) throws RemoteException {
-        return getImplForUser().getAppWidgetViews(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetViews(appWidgetId);
     }
 
     @Override
     public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
-        getImplForUser().updateAppWidgetOptions(appWidgetId, options);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetOptions(appWidgetId, options);
     }
 
     @Override
     public Bundle getAppWidgetOptions(int appWidgetId) {
-        return getImplForUser().getAppWidgetOptions(appWidgetId);
+        return getImplForUser(UserHandle.getCallingUserId()).getAppWidgetOptions(appWidgetId);
     }
 
     static int[] getAppWidgetIds(Provider p) {
@@ -299,40 +305,43 @@
 
     @Override
     public List<AppWidgetProviderInfo> getInstalledProviders() throws RemoteException {
-        return getImplForUser().getInstalledProviders();
+        return getImplForUser(UserHandle.getCallingUserId()).getInstalledProviders();
     }
 
     @Override
     public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId)
             throws RemoteException {
-        getImplForUser().notifyAppWidgetViewDataChanged(appWidgetIds, viewId);
+        getImplForUser(UserHandle.getCallingUserId()).notifyAppWidgetViewDataChanged(
+                appWidgetIds, viewId);
     }
 
     @Override
     public void partiallyUpdateAppWidgetIds(int[] appWidgetIds, RemoteViews views)
             throws RemoteException {
-        getImplForUser().partiallyUpdateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(UserHandle.getCallingUserId()).partiallyUpdateAppWidgetIds(
+                appWidgetIds, views);
     }
 
     @Override
     public void stopListening(int hostId) throws RemoteException {
-        getImplForUser().stopListening(hostId);
+        getImplForUser(UserHandle.getCallingUserId()).stopListening(hostId);
     }
 
     @Override
     public void unbindRemoteViewsService(int appWidgetId, Intent intent) throws RemoteException {
-        getImplForUser().unbindRemoteViewsService(appWidgetId, intent);
+        getImplForUser(UserHandle.getCallingUserId()).unbindRemoteViewsService(
+                appWidgetId, intent);
     }
 
     @Override
     public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) throws RemoteException {
-        getImplForUser().updateAppWidgetIds(appWidgetIds, views);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetIds(appWidgetIds, views);
     }
 
     @Override
     public void updateAppWidgetProvider(ComponentName provider, RemoteViews views)
             throws RemoteException {
-        getImplForUser().updateAppWidgetProvider(provider, views);
+        getImplForUser(UserHandle.getCallingUserId()).updateAppWidgetProvider(provider, views);
     }
 
     @Override
@@ -349,7 +358,12 @@
             String action = intent.getAction();
             // Slog.d(TAG, "received " + action);
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
-                getImplForUser().sendInitialBroadcasts();
+                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                if (userId >= 0) {
+                    getImplForUser(userId).sendInitialBroadcasts();
+                } else {
+                    Slog.w(TAG, "Not user handle supplied in " + intent);
+                }
             } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
                 for (int i = 0; i < mAppWidgetServices.size(); i++) {
                     AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i);
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 79dabee..57ab921 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -40,6 +40,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -1634,11 +1635,11 @@
     }
 
     static File getSettingsFile(int userId) {
-        return new File("/data/system/users/" + userId + "/" + SETTINGS_FILENAME);
+        return new File(Environment.getUserSystemDirectory(userId), SETTINGS_FILENAME);
     }
 
     AtomicFile savedStateFile() {
-        File dir = new File("/data/system/users/" + mUserId);
+        File dir = Environment.getUserSystemDirectory(mUserId);
         File settingsFile = getSettingsFile(mUserId);
         if (!settingsFile.exists() && mUserId == 0) {
             if (!dir.exists()) {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 8be0ba8..955ea23 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1663,8 +1663,7 @@
         synchronized(mClearDataLock) {
             mClearingData = true;
             try {
-                mActivityManager.clearApplicationUserData(packageName, observer,
-                        Binder.getOrigCallingUser());
+                mActivityManager.clearApplicationUserData(packageName, observer, 0);
             } catch (RemoteException e) {
                 // can't happen because the activity manager is in this process
             }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index e45cee3..40f6ecf 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -20,6 +20,7 @@
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.IActivityManager;
@@ -318,17 +319,20 @@
         final int id;
         final int uid;
         final int initialPid;
+        final int userId;
         final Notification notification;
         final int score;
         IBinder statusBarKey;
 
-        NotificationRecord(String pkg, String tag, int id, int uid, int initialPid, int score, Notification notification)
+        NotificationRecord(String pkg, String tag, int id, int uid, int initialPid,
+                int userId, int score, Notification notification)
         {
             this.pkg = pkg;
             this.tag = tag;
             this.id = id;
             this.uid = uid;
             this.initialPid = initialPid;
+            this.userId = userId;
             this.score = score;
             this.notification = notification;
         }
@@ -343,7 +347,7 @@
             pw.println(prefix + "  deleteIntent=" + notification.deleteIntent);
             pw.println(prefix + "  tickerText=" + notification.tickerText);
             pw.println(prefix + "  contentView=" + notification.contentView);
-            pw.println(prefix + "  uid=" + uid);
+            pw.println(prefix + "  uid=" + uid + " userId=" + userId);
             pw.println(prefix + "  defaults=0x" + Integer.toHexString(notification.defaults));
             pw.println(prefix + "  flags=0x" + Integer.toHexString(notification.flags));
             pw.println(prefix + "  sound=" + notification.sound);
@@ -430,18 +434,25 @@
         }
 
         public void onClearAll() {
-            cancelAll();
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
+            cancelAll(ActivityManager.getCurrentUser());
         }
 
         public void onNotificationClick(String pkg, String tag, int id) {
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
             cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
-                    Notification.FLAG_FOREGROUND_SERVICE, false);
+                    Notification.FLAG_FOREGROUND_SERVICE, false,
+                    ActivityManager.getCurrentUser());
         }
 
         public void onNotificationClear(String pkg, String tag, int id) {
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
             cancelNotification(pkg, tag, id, 0,
                 Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
-                true);
+                true, ActivityManager.getCurrentUser());
         }
 
         public void onPanelRevealed() {
@@ -480,7 +491,9 @@
                 int uid, int initialPid, String message) {
             Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
                     + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
-            cancelNotification(pkg, tag, id, 0, 0, false);
+            // XXX to be totally correct, the caller should tell us which user
+            // this is for.
+            cancelNotification(pkg, tag, id, 0, 0, false, UserHandle.getUserId(uid));
             long ident = Binder.clearCallingIdentity();
             try {
                 ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
@@ -532,7 +545,8 @@
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
-                        cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart);
+                        cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
+                                UserHandle.USER_ALL);
                     }
                 }
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
@@ -548,7 +562,7 @@
             } else if (action.equals(Intent.ACTION_USER_STOPPED)) {
                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                 if (userHandle >= 0) {
-                    cancelAllNotificationsUser(userHandle);
+                    cancelAllNotificationsInt(null, 0, 0, true, userHandle);
                 }
             } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                 // turn off LED when user passes through lock screen
@@ -856,17 +870,11 @@
 
     // Notifications
     // ============================================================================
-    @Deprecated
-    public void enqueueNotification(String pkg, int id, Notification notification, int[] idOut)
-    {
-        enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut);
-    }
-
     public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,
-            int[] idOut)
+            int[] idOut, int userId)
     {
         enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),
-                tag, id, notification, idOut);
+                tag, id, notification, idOut, userId);
     }
     
     private final static int clamp(int x, int low, int high) {
@@ -877,7 +885,7 @@
     // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
     // uid/pid of another application)
     public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
-            String tag, int id, Notification notification, int[] idOut)
+            String tag, int id, Notification notification, int[] idOut, int userId)
     {
         if (DBG) {
             Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
@@ -885,6 +893,9 @@
         checkCallerIsSystemOrSameApp(pkg);
         final boolean isSystemNotification = ("android".equals(pkg));
 
+        userId = ActivityManager.handleIncomingUser(callingPid,
+                callingUid, userId, false, true, "enqueueNotification", pkg);
+
         // Limit the number of notifications that any given package except the android
         // package can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification) {
@@ -959,12 +970,12 @@
 
         synchronized (mNotificationList) {
             NotificationRecord r = new NotificationRecord(pkg, tag, id, 
-                    callingUid, callingPid, 
+                    callingUid, callingPid, userId,
                     score,
                     notification);
             NotificationRecord old = null;
 
-            int index = indexOfNotificationLocked(pkg, tag, id);
+            int index = indexOfNotificationLocked(pkg, tag, id, userId);
             if (index < 0) {
                 mNotificationList.add(r);
             } else {
@@ -1195,12 +1206,12 @@
      * and none of the {@code mustNotHaveFlags}.
      */
     private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags,
-            int mustNotHaveFlags, boolean sendDelete) {
+            int mustNotHaveFlags, boolean sendDelete, int userId) {
         EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag,
                 mustHaveFlags, mustNotHaveFlags);
 
         synchronized (mNotificationList) {
-            int index = indexOfNotificationLocked(pkg, tag, id);
+            int index = indexOfNotificationLocked(pkg, tag, id, userId);
             if (index >= 0) {
                 NotificationRecord r = mNotificationList.get(index);
 
@@ -1224,7 +1235,7 @@
      * {@code mustHaveFlags}.
      */
     boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
-            int mustNotHaveFlags, boolean doit) {
+            int mustNotHaveFlags, boolean doit, int userId) {
         EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags,
                 mustNotHaveFlags);
 
@@ -1233,6 +1244,9 @@
             boolean canceledSomething = false;
             for (int i = N-1; i >= 0; --i) {
                 NotificationRecord r = mNotificationList.get(i);
+                if (userId != UserHandle.USER_ALL && r.userId != userId) {
+                    continue;
+                }
                 if ((r.notification.flags & mustHaveFlags) != mustHaveFlags) {
                     continue;
                 }
@@ -1256,48 +1270,25 @@
         }
     }
 
-    /**
-     * Cancels all notifications from a given user.
-     */
-    boolean cancelAllNotificationsUser(int userHandle) {
-        synchronized (mNotificationList) {
-            final int N = mNotificationList.size();
-            boolean canceledSomething = false;
-            for (int i = N-1; i >= 0; --i) {
-                NotificationRecord r = mNotificationList.get(i);
-                if (UserHandle.getUserId(r.uid) != userHandle) {
-                    continue;
-                }
-                canceledSomething = true;
-                mNotificationList.remove(i);
-                cancelNotificationLocked(r, false);
-            }
-            if (canceledSomething) {
-                updateLightsLocked();
-            }
-            return canceledSomething;
-        }
-    }
-
-    @Deprecated
-    public void cancelNotification(String pkg, int id) {
-        cancelNotificationWithTag(pkg, null /* tag */, id);
-    }
-
-    public void cancelNotificationWithTag(String pkg, String tag, int id) {
+    public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
         checkCallerIsSystemOrSameApp(pkg);
+        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, false, true, "cancelNotificationWithTag", pkg);
         // Don't allow client applications to cancel foreground service notis.
         cancelNotification(pkg, tag, id, 0,
                 Binder.getCallingUid() == Process.SYSTEM_UID
-                ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false);
+                ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId);
     }
 
-    public void cancelAllNotifications(String pkg) {
+    public void cancelAllNotifications(String pkg, int userId) {
         checkCallerIsSystemOrSameApp(pkg);
 
+        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                Binder.getCallingUid(), userId, true, true, "cancelAllNotifications", pkg);
+
         // Calling from user space, don't allow the canceling of actively
         // running foreground services.
-        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true);
+        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
     }
 
     void checkCallerIsSystem() {
@@ -1325,12 +1316,16 @@
         }
     }
 
-    void cancelAll() {
+    void cancelAll(int userId) {
         synchronized (mNotificationList) {
             final int N = mNotificationList.size();
             for (int i=N-1; i>=0; i--) {
                 NotificationRecord r = mNotificationList.get(i);
 
+                if (r.userId != userId) {
+                    continue;
+                }
+
                 if ((r.notification.flags & (Notification.FLAG_ONGOING_EVENT
                                 | Notification.FLAG_NO_CLEAR)) == 0) {
                     mNotificationList.remove(i);
@@ -1375,12 +1370,15 @@
     }
 
     // lock on mNotificationList
-    private int indexOfNotificationLocked(String pkg, String tag, int id)
+    private int indexOfNotificationLocked(String pkg, String tag, int id, int userId)
     {
         ArrayList<NotificationRecord> list = mNotificationList;
         final int len = list.size();
         for (int i=0; i<len; i++) {
             NotificationRecord r = list.get(i);
+            if (r.userId != userId || r.id != id) {
+                continue;
+            }
             if (tag == null) {
                 if (r.tag != null) {
                     continue;
@@ -1390,7 +1388,7 @@
                     continue;
                 }
             }
-            if (r.id == id && r.pkg.equals(pkg)) {
+            if (r.pkg.equals(pkg)) {
                 return i;
             }
         }
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 78c0c12..9f53fad 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -27,7 +27,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
-import android.view.View;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index a7a583c..8cf273d 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -24,8 +24,10 @@
 import android.app.backup.FullBackupDataOutput;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.Context;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.Slog;
 
 
@@ -45,11 +47,13 @@
     private static final String WALLPAPER_INFO_FILENAME = "wallpaper_info.xml";
 
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String WALLPAPER_IMAGE_DIR = "/data/system/users/0";
+    private static final String WALLPAPER_IMAGE_DIR =
+            Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
     private static final String WALLPAPER_IMAGE = WallpaperBackupHelper.WALLPAPER_IMAGE;
 
     // TODO: Will need to change if backing up non-primary user's wallpaper
-    private static final String WALLPAPER_INFO_DIR = "/data/system/users/0";
+    private static final String WALLPAPER_INFO_DIR =
+            Environment.getUserSystemDirectory(UserHandle.USER_OWNER).getAbsolutePath();
     private static final String WALLPAPER_INFO = WallpaperBackupHelper.WALLPAPER_INFO;
     // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
     private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 4900e00..f618263 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -165,7 +165,7 @@
                     try {
                         ActivityManagerNative.getDefault().startActivityWithConfig(
                                 null, homeIntent, null, null, null, 0, 0,
-                                newConfig, null);
+                                newConfig, null, UserHandle.USER_CURRENT);
                         mHoldingConfiguration = false;
                     } catch (RemoteException e) {
                         Slog.w(TAG, e.getCause());
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 643e937..a807f4c 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -92,8 +92,6 @@
      * restarting it vs. just reverting to the static wallpaper.
      */
     static final long MIN_WALLPAPER_CRASH_TIME = 10000;
-    
-    static final File WALLPAPER_BASE_DIR = new File("/data/system/users");
     static final String WALLPAPER = "wallpaper";
     static final String WALLPAPER_INFO = "wallpaper_info.xml";
 
@@ -395,12 +393,12 @@
         mIPackageManager = AppGlobals.getPackageManager();
         mMonitor = new MyPackageMonitor();
         mMonitor.register(context, null, true);
-        WALLPAPER_BASE_DIR.mkdirs();
-        loadSettingsLocked(0);
+        getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
+        loadSettingsLocked(UserHandle.USER_OWNER);
     }
     
     private static File getWallpaperDir(int userId) {
-        return new File(WALLPAPER_BASE_DIR + "/" + userId);
+        return Environment.getUserSystemDirectory(userId);
     }
 
     @Override
@@ -414,7 +412,7 @@
 
     public void systemReady() {
         if (DEBUG) Slog.v(TAG, "systemReady");
-        WallpaperData wallpaper = mWallpaperMap.get(0);
+        WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
         switchWallpaper(wallpaper);
         wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
         wallpaper.wallpaperObserver.startWatching();
@@ -776,11 +774,11 @@
             intent.setComponent(componentName);
             intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                     com.android.internal.R.string.wallpaper_binding_label);
-            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
                     mContext, 0,
                     Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
                             mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
-                            0));
+                    0, null, new UserHandle(serviceUserId)));
             if (!mContext.bindService(intent, newConn, Context.BIND_AUTO_CREATE, serviceUserId)) {
                 String msg = "Unable to bind service: "
                         + componentName;
@@ -880,7 +878,7 @@
     }
 
     private static JournaledFile makeJournaledFile(int userId) {
-        final String base = getWallpaperDir(userId) + "/" + WALLPAPER_INFO;
+        final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
         return new JournaledFile(new File(base), new File(base + ".tmp"));
     }
 
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index e836e77..6a3010b 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -323,7 +323,7 @@
             int startId) {
         if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
                 + " " + token + " startId=" + startId);
-        ServiceRecord r = findServiceLocked(className, token);
+        ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
         if (r != null) {
             if (startId >= 0) {
                 // Asked to only stop if done with all work.  Note that
@@ -366,9 +366,10 @@
 
     public void setServiceForegroundLocked(ComponentName className, IBinder token,
             int id, Notification notification, boolean removeNotification) {
+        final int userId = UserHandle.getCallingUserId();
         final long origId = Binder.clearCallingIdentity();
         try {
-            ServiceRecord r = findServiceLocked(className, token);
+            ServiceRecord r = findServiceLocked(className, token, userId);
             if (r != null) {
                 if (id != 0) {
                     if (notification == null) {
@@ -427,9 +428,6 @@
         if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
                 + " type=" + resolvedType + " conn=" + connection.asBinder()
                 + " flags=0x" + Integer.toHexString(flags));
-        if (DEBUG_MU)
-            Slog.i(TAG_MU, "bindService uid=" + Binder.getCallingUid() + " origUid="
-                    + Binder.getOrigCallingUid());
         final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
         if (callerApp == null) {
             throw new SecurityException(
@@ -677,8 +675,8 @@
     }
 
     private final ServiceRecord findServiceLocked(ComponentName name,
-            IBinder token) {
-        ServiceRecord r = mServiceMap.getServiceByName(name, Binder.getOrigCallingUser());
+            IBinder token, int userId) {
+        ServiceRecord r = mServiceMap.getServiceByName(name, userId);
         return r == token ? r : null;
     }
 
@@ -1424,9 +1422,6 @@
                     r.callStart = false;
                 }
             }
-            if (DEBUG_MU)
-                Slog.v(TAG_MU, "before serviceDontExecutingLocked, uid="
-                        + Binder.getOrigCallingUid());
             final long origId = Binder.clearCallingIdentity();
             serviceDoneExecutingLocked(r, inStopping);
             Binder.restoreCallingIdentity(origId);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6c87252..590e9d9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1129,13 +1129,15 @@
                     notification.vibrate = null;
                     notification.setLatestEventInfo(context, text,
                             mContext.getText(R.string.heavy_weight_notification_detail),
-                            PendingIntent.getActivity(mContext, 0, root.intent,
-                                    PendingIntent.FLAG_CANCEL_CURRENT));
+                            PendingIntent.getActivityAsUser(mContext, 0, root.intent,
+                                    PendingIntent.FLAG_CANCEL_CURRENT, null,
+                                    new UserHandle(root.userId)));
                     
                     try {
                         int[] outId = new int[1];
-                        inm.enqueueNotification("android", R.string.heavy_weight_notification,
-                                notification, outId);
+                        inm.enqueueNotificationWithTag("android", null,
+                                R.string.heavy_weight_notification,
+                                notification, outId, root.userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error showing notification for heavy-weight app", e);
@@ -1151,8 +1153,8 @@
                     return;
                 }
                 try {
-                    inm.cancelNotification("android",
-                            R.string.heavy_weight_notification);
+                    inm.cancelNotificationWithTag("android", null,
+                            R.string.heavy_weight_notification,  msg.arg1);
                 } catch (RuntimeException e) {
                     Slog.w(ActivityManagerService.TAG,
                             "Error canceling notification for service", e);
@@ -2371,14 +2373,6 @@
                 // Requesting home, set the identity to the current user
                 // HACK!
                 userId = mCurrentUserId;
-            } else {
-                // TODO: Fix this in a better way - calls coming from SystemUI should probably carry
-                // the current user's userId
-                if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
-                    userId = 0;
-                } else {
-                    userId = Binder.getOrigCallingUser();
-                }
             }
         }
         return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
@@ -2392,21 +2386,22 @@
             ParcelFileDescriptor profileFd, Bundle options) {
         enforceNotIsolatedCaller("startActivityAndWait");
         WaitResult res = new WaitResult();
-        int userId = Binder.getOrigCallingUser();
         mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
-                res, null, options, userId);
+                res, null, options, UserHandle.getCallingUserId());
         return res;
     }
 
     public final int startActivityWithConfig(IApplicationThread caller,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, Configuration config,
-            Bundle options) {
+            Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivityWithConfig");
+        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityWithConfig", null);
         int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, config, options, Binder.getOrigCallingUser());
+                null, null, null, config, options, userId);
         return ret;
     }
 
@@ -2537,21 +2532,16 @@
         }
     }
 
-    public final int startActivityInPackage(int uid,
+    final int startActivityInPackage(int uid,
             Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, Bundle options) {
-        
-        // This is so super not safe, that only the system (or okay root)
-        // can do it.
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            throw new SecurityException(
-                    "startActivityInPackage only available to the system");
-        }
+            String resultWho, int requestCode, int startFlags, Bundle options, int userId) {
+
+        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityInPackage", null);
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
-                null, null, null, null, options, UserHandle.getUserId(uid));
+                null, null, null, null, options, userId);
         return ret;
     }
 
@@ -2559,23 +2549,18 @@
             Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options) {
         enforceNotIsolatedCaller("startActivities");
         int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
-                options, Binder.getOrigCallingUser());
+                options, UserHandle.getCallingUserId());
         return ret;
     }
 
-    public final int startActivitiesInPackage(int uid,
+    final int startActivitiesInPackage(int uid,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) {
+            Bundle options, int userId) {
 
-        // This is so super not safe, that only the system (or okay root)
-        // can do it.
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.myUid()) {
-            throw new SecurityException(
-                    "startActivityInPackage only available to the system");
-        }
+        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivityInPackage", null);
         int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
-                options, UserHandle.getUserId(uid));
+                options, userId);
         return ret;
     }
 
@@ -2709,8 +2694,9 @@
                 }
             }
             
+            mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                    mHeavyWeightProcess.userId, 0));
             mHeavyWeightProcess = null;
-            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
         }
     }
     
@@ -3884,8 +3870,9 @@
         mProcessNames.remove(name, uid);
         mIsolatedProcesses.remove(app.uid);
         if (mHeavyWeightProcess == app) {
+            mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                    mHeavyWeightProcess.userId, 0));
             mHeavyWeightProcess = null;
-            mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
         }
         boolean needRestart = false;
         if (app.pid > 0 && app.pid != MY_PID) {
@@ -3931,8 +3918,9 @@
             mProcessNames.remove(app.processName, app.uid);
             mIsolatedProcesses.remove(app.uid);
             if (mHeavyWeightProcess == app) {
+                mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                        mHeavyWeightProcess.userId, 0));
                 mHeavyWeightProcess = null;
-                mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
             }
             // Take care of any launching providers waiting for this process.
             checkAppInLaunchingProvidersLocked(app, true);
@@ -4288,12 +4276,13 @@
                     UserStartedState uss = mStartedUsers.valueAt(i);
                     if (uss.mState == UserStartedState.STATE_BOOTING) {
                         uss.mState = UserStartedState.STATE_RUNNING;
-                        broadcastIntentLocked(null, null,
-                                new Intent(Intent.ACTION_BOOT_COMPLETED, null),
+                        final int userId = mStartedUsers.keyAt(i);
+                        Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+                        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                        broadcastIntentLocked(null, null, intent,
                                 null, null, 0, null, null,
                                 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
-                                false, false, MY_PID, Process.SYSTEM_UID,
-                                mStartedUsers.keyAt(i));
+                                false, false, MY_PID, Process.SYSTEM_UID, userId);
                     }
                 }
             }
@@ -4405,7 +4394,7 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes,
-            int flags, Bundle options) {
+            int flags, Bundle options, int userId) {
         enforceNotIsolatedCaller("getIntentSender");
         // Refuse possible leaked file descriptors
         if (intents != null) {
@@ -4439,6 +4428,8 @@
         
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
+            userId = handleIncomingUserLocked(Binder.getCallingPid(), callingUid, userId,
+                    false, true, "getIntentSender", null);
             try {
                 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
                     int uid = AppGlobals.getPackageManager()
@@ -4453,11 +4444,8 @@
                         throw new SecurityException(msg);
                     }
                 }
-                
-                if (DEBUG_MU)
-                    Slog.i(TAG_MU, "Getting intent sender for origCallingUid="
-                            + Binder.getOrigCallingUid());
-                return getIntentSenderLocked(type, packageName, Binder.getOrigCallingUid(),
+
+                return getIntentSenderLocked(type, packageName, callingUid, userId,
                         token, resultWho, requestCode, intents, resolvedTypes, flags, options);
                 
             } catch (RemoteException e) {
@@ -4466,8 +4454,8 @@
         }
     }
     
-    IIntentSender getIntentSenderLocked(int type,
-            String packageName, int callingUid, IBinder token, String resultWho,
+    IIntentSender getIntentSenderLocked(int type, String packageName,
+            int callingUid, int userId, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags,
             Bundle options) {
         if (DEBUG_MU)
@@ -4491,8 +4479,7 @@
 
         PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                 type, packageName, activity, resultWho,
-                requestCode, intents, resolvedTypes, flags, options,
-                UserHandle.getUserId(callingUid));
+                requestCode, intents, resolvedTypes, flags, options, userId);
         WeakReference<PendingIntentRecord> ref;
         ref = mIntentSenderRecords.get(key);
         PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -6233,7 +6220,7 @@
     }
 
     private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
-            String name, IBinder token, boolean stable) {
+            String name, IBinder token, boolean stable, int userId) {
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
@@ -6248,10 +6235,13 @@
                           + " (pid=" + Binder.getCallingPid()
                           + ") when getting content provider " + name);
                 }
+                if (r.userId != userId) {
+                    throw new SecurityException("Calling requested user " + userId
+                            + " but app is user " + r.userId);
+                }
             }
 
             // First check if this content provider has been published...
-            int userId = UserHandle.getUserId(r != null ? r.uid : Binder.getCallingUid());
             cpr = mProviderMap.getProviderByName(name, userId);
             boolean providerRunning = cpr != null;
             if (providerRunning) {
@@ -6506,17 +6496,19 @@
             throw new SecurityException(msg);
         }
 
-        return getContentProviderImpl(caller, name, null, stable);
+        return getContentProviderImpl(caller, name, null, stable,
+                UserHandle.getCallingUserId());
     }
 
     public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call getContentProviderExternal()");
-        return getContentProviderExternalUnchecked(name, token);
+        return getContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
     }
 
-    private ContentProviderHolder getContentProviderExternalUnchecked(String name,IBinder token) {
-        return getContentProviderImpl(null, name, token, true);
+    private ContentProviderHolder getContentProviderExternalUnchecked(String name,
+            IBinder token, int userId) {
+        return getContentProviderImpl(null, name, token, true, userId);
     }
 
     /**
@@ -6547,13 +6539,12 @@
     public void removeContentProviderExternal(String name, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call removeContentProviderExternal()");
-        removeContentProviderExternalUnchecked(name, token);
+        removeContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
     }
 
-    private void removeContentProviderExternalUnchecked(String name, IBinder token) {
+    private void removeContentProviderExternalUnchecked(String name, IBinder token, int userId) {
         synchronized (this) {
-            ContentProviderRecord cpr = mProviderMap.getProviderByName(name,
-                    Binder.getOrigCallingUser());
+            ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
             if(cpr == null) {
                 //remove from mProvidersByClass
                 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
@@ -6562,8 +6553,7 @@
 
             //update content provider record entry info
             ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
-            ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp,
-                    Binder.getOrigCallingUser());
+            ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
             if (localCpr.hasExternalProcessHandles()) {
                 if (localCpr.removeExternalProcessHandleLocked(token)) {
                     updateOomAdjLocked();
@@ -6777,11 +6767,12 @@
     public String getProviderMimeType(Uri uri) {
         enforceNotIsolatedCaller("getProviderMimeType");
         final String name = uri.getAuthority();
+        final int userId = UserHandle.getCallingUserId();
         final long ident = Binder.clearCallingIdentity();
         ContentProviderHolder holder = null;
 
         try {
-            holder = getContentProviderExternalUnchecked(name, null);
+            holder = getContentProviderExternalUnchecked(name, null, userId);
             if (holder != null) {
                 return holder.provider.getType(uri);
             }
@@ -6790,7 +6781,7 @@
             return null;
         } finally {
             if (holder != null) {
-                removeContentProviderExternalUnchecked(name, null);
+                removeContentProviderExternalUnchecked(name, null, userId);
             }
             Binder.restoreCallingIdentity(ident);
         }
@@ -6894,8 +6885,9 @@
 
     public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
         enforceNotIsolatedCaller("openContentUri");
+        final int userId = UserHandle.getCallingUserId();
         String name = uri.getAuthority();
-        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null);
+        ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
         ParcelFileDescriptor pfd = null;
         if (cph != null) {
             // We record the binder invoker's uid in thread-local storage before
@@ -6917,7 +6909,7 @@
             }
 
             // We've got the fd now, so we're done with the provider.
-            removeContentProviderExternalUnchecked(name, null);
+            removeContentProviderExternalUnchecked(name, null, userId);
         } else {
             Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
         }
@@ -10562,8 +10554,9 @@
             mProcessNames.remove(app.processName, app.uid);
             mIsolatedProcesses.remove(app.uid);
             if (mHeavyWeightProcess == app) {
+                mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
+                        mHeavyWeightProcess.userId, 0));
                 mHeavyWeightProcess = null;
-                mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
             }
         } else if (!app.removed) {
             // This app is persistent, so we need to keep its record around.
@@ -10663,13 +10656,13 @@
     }
 
     ComponentName startServiceInPackage(int uid,
-            Intent service, String resolvedType) {
+            Intent service, String resolvedType, int userId) {
         synchronized(this) {
             if (DEBUG_SERVICE)
                 Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
             final long origId = Binder.clearCallingIdentity();
             ComponentName res = mServices.startServiceLocked(null, service,
-                    resolvedType, -1, uid, UserHandle.getUserId(uid));
+                    resolvedType, -1, uid, userId);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
@@ -10716,6 +10709,14 @@
         }
     }
 
+    public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+            boolean requireFull, String name, String callerPackage) {
+        synchronized(this) {
+            return handleIncomingUserLocked(callingPid, callingUid, userId, allowAll,
+                    requireFull, name, callerPackage);
+        }        
+    }
+
     int handleIncomingUserLocked(int callingPid, int callingUid, int userId, boolean allowAll,
             boolean requireFull, String name, String callerPackage) {
         final int callingUserId = UserHandle.getUserId(callingUid);
@@ -10733,13 +10734,24 @@
                         // owner user instead of failing.
                         userId = callingUserId;
                     } else {
-                        String msg = "Permission Denial: " + name + " from " + callerPackage
-                                + " asks to run as user " + userId
-                                + " but is calling from user " + UserHandle.getUserId(callingUid)
-                                + "; this requires "
-                                + (requireFull
-                                        ? android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
-                                        : android.Manifest.permission.INTERACT_ACROSS_USERS);
+                        StringBuilder builder = new StringBuilder(128);
+                        builder.append("Permission Denial: ");
+                        builder.append(name);
+                        if (callerPackage != null) {
+                            builder.append(" from ");
+                            builder.append(callerPackage);
+                        }
+                        builder.append(" asks to run as user ");
+                        builder.append(userId);
+                        builder.append(" but is calling from user ");
+                        builder.append(UserHandle.getUserId(callingUid));
+                        builder.append("; this requires ");
+                        builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+                        if (!requireFull) {
+                            builder.append("or");
+                            builder.append(android.Manifest.permission.INTERACT_ACROSS_USERS);
+                        }
+                        String msg = builder.toString();
                         Slog.w(TAG, msg);
                         throw new SecurityException(msg);
                     }
@@ -13760,11 +13772,13 @@
             if (uss.mState == UserStartedState.STATE_BOOTING
                     && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
                 uss.mState = UserStartedState.STATE_RUNNING;
-                broadcastIntentLocked(null, null,
-                        new Intent(Intent.ACTION_BOOT_COMPLETED, null),
+                final int userId = uss.mHandle.getIdentifier();
+                Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+                broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null,
                         android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
-                        false, false, MY_PID, Process.SYSTEM_UID, uss.mHandle.getIdentifier());
+                        false, false, MY_PID, Process.SYSTEM_UID, userId);
             }
         }
     }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index ef4e9be..399ea59 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3077,7 +3077,7 @@
                         
                         IIntentSender target = mService.getIntentSenderLocked(
                                 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
-                                realCallingUid, null, null, 0, new Intent[] { intent },
+                                realCallingUid, userId, null, null, 0, new Intent[] { intent },
                                 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
                                 | PendingIntent.FLAG_ONE_SHOT, null);
                         
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 8e70376..37e9017 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -243,11 +243,10 @@
                                 allIntents[allIntents.length-1] = finalIntent;
                                 allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
                                 owner.startActivitiesInPackage(uid, allIntents,
-                                        allResolvedTypes, resultTo, options);
+                                        allResolvedTypes, resultTo, options, key.userId);
                             } else {
-                                owner.startActivityInPackage(uid,
-                                        finalIntent, resolvedType,
-                                        resultTo, resultWho, requestCode, 0, options);
+                                owner.startActivityInPackage(uid, finalIntent, resolvedType,
+                                        resultTo, resultWho, requestCode, 0, options, key.userId);
                             }
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -265,8 +264,7 @@
                             owner.broadcastIntentInPackage(key.packageName, uid,
                                     finalIntent, resolvedType,
                                     finishedReceiver, code, null, null,
-                                requiredPermission, (finishedReceiver != null), false, UserHandle
-                                        .getUserId(uid));
+                                requiredPermission, (finishedReceiver != null), false, key.userId);
                             sendFinish = false;
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
@@ -276,7 +274,7 @@
                     case ActivityManager.INTENT_SENDER_SERVICE:
                         try {
                             owner.startServiceInPackage(uid,
-                                    finalIntent, resolvedType);
+                                    finalIntent, resolvedType, key.userId);
                         } catch (RuntimeException e) {
                             Slog.w(ActivityManagerService.TAG,
                                     "Unable to send startService intent", e);
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 15fbb98..7a4fef6 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -116,48 +116,46 @@
         }
     }
 
-    void removeProviderByName(String name, int optionalUserId) {
+    void removeProviderByName(String name, int userId) {
         if (mSingletonByName.containsKey(name)) {
             if (DBG)
                 Slog.i(TAG, "Removing from globalByName name=" + name);
             mSingletonByName.remove(name);
         } else {
-            // TODO: Verify this works, i.e., the caller happens to be from the correct user
+            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
             if (DBG)
                 Slog.i(TAG,
-                        "Removing from providersByName name=" + name + " user="
-                        + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            HashMap<String, ContentProviderRecord> map = getProvidersByName(optionalUserId);
+                        "Removing from providersByName name=" + name + " user=" + userId);
+            HashMap<String, ContentProviderRecord> map = getProvidersByName(userId);
             // map returned by getProvidersByName wouldn't be null
             map.remove(name);
             if (map.size() == 0) {
-                mProvidersByNamePerUser.remove(optionalUserId);
+                mProvidersByNamePerUser.remove(userId);
             }
         }
     }
 
-    void removeProviderByClass(ComponentName name, int optionalUserId) {
+    void removeProviderByClass(ComponentName name, int userId) {
         if (mSingletonByClass.containsKey(name)) {
             if (DBG)
                 Slog.i(TAG, "Removing from globalByClass name=" + name);
             mSingletonByClass.remove(name);
         } else {
+            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
             if (DBG)
                 Slog.i(TAG,
-                        "Removing from providersByClass name=" + name + " user="
-                        + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId));
-            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(optionalUserId);
+                        "Removing from providersByClass name=" + name + " user=" + userId);
+            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(userId);
             // map returned by getProvidersByClass wouldn't be null
             map.remove(name);
             if (map.size() == 0) {
-                mProvidersByClassPerUser.remove(optionalUserId);
+                mProvidersByClassPerUser.remove(userId);
             }
         }
     }
 
-    private HashMap<String, ContentProviderRecord> getProvidersByName(int optionalUserId) {
-        final int userId = optionalUserId >= 0
-                ? optionalUserId : Binder.getOrigCallingUser();
+    private HashMap<String, ContentProviderRecord> getProvidersByName(int userId) {
+        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
         final HashMap<String, ContentProviderRecord> map = mProvidersByNamePerUser.get(userId);
         if (map == null) {
             HashMap<String, ContentProviderRecord> newMap = new HashMap<String, ContentProviderRecord>();
@@ -168,12 +166,13 @@
         }
     }
 
-    HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int optionalUserId) {
-        final int userId = optionalUserId >= 0
-                ? optionalUserId : Binder.getOrigCallingUser();
-        final HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.get(userId);
+    HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int userId) {
+        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
+        final HashMap<ComponentName, ContentProviderRecord> map
+                = mProvidersByClassPerUser.get(userId);
         if (map == null) {
-            HashMap<ComponentName, ContentProviderRecord> newMap = new HashMap<ComponentName, ContentProviderRecord>();
+            HashMap<ComponentName, ContentProviderRecord> newMap
+                    = new HashMap<ComponentName, ContentProviderRecord>();
             mProvidersByClassPerUser.put(userId, newMap);
             return newMap;
         } else {
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 5d60b9c..7055fdc 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -370,7 +370,7 @@
                     try {
                         int[] outId = new int[1];
                         nm.enqueueNotificationInternal(localPackageName, appUid, appPid,
-                                null, localForegroundId, localForegroundNoti, outId);
+                                null, localForegroundId, localForegroundNoti, outId, userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error showing notification for service", e);
@@ -399,7 +399,8 @@
                         return;
                     }
                     try {
-                        inm.cancelNotification(localPackageName, localForegroundId);
+                        inm.cancelNotificationWithTag(localPackageName, null,
+                                localForegroundId, userId);
                     } catch (RuntimeException e) {
                         Slog.w(ActivityManagerService.TAG,
                                 "Error canceling notification for service", e);
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index c6e66cf..46bddc4 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -788,11 +788,13 @@
         }
 
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             final int[] idReceived = new int[1];
             mNotifManager.enqueueNotificationWithTag(
-                    packageName, tag, 0x0, builder.getNotification(), idReceived);
+                    packageName, tag, 0x0, builder.getNotification(), idReceived,
+                    UserHandle.USER_OWNER);
             mActiveNotifs.add(tag);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
@@ -822,11 +824,12 @@
                 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
 
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             final int[] idReceived = new int[1];
             mNotifManager.enqueueNotificationWithTag(packageName, tag,
-                    0x0, builder.getNotification(), idReceived);
+                    0x0, builder.getNotification(), idReceived, UserHandle.USER_OWNER);
             mActiveNotifs.add(tag);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
@@ -835,10 +838,11 @@
 
     private void cancelNotification(String tag) {
         // TODO: move to NotificationManager once we can mock it
+        // XXX what to do about multi-user?
         try {
             final String packageName = mContext.getPackageName();
             mNotifManager.cancelNotificationWithTag(
-                    packageName, tag, 0x0);
+                    packageName, tag, 0x0, UserHandle.USER_OWNER);
         } catch (RemoteException e) {
             // ignored; service lives in system_server
         }
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 68b594a..5f10d44 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -745,13 +745,12 @@
     }
 
     private File getUserPackagesStateFile(int userId) {
-        return new File(mSystemDir,
-                "users/" + userId + "/package-restrictions.xml");
+        return new File(Environment.getUserSystemDirectory(userId), "package-restrictions.xml");
     }
 
     private File getUserPackagesStateBackupFile(int userId) {
-        return new File(mSystemDir,
-                "users/" + userId + "/package-restrictions-backup.xml");
+        return new File(Environment.getUserSystemDirectory(userId),
+                "package-restrictions-backup.xml");
     }
 
     void writeAllUsersPackageRestrictionsLPr() {
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 492158d..a13c16e 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -594,6 +594,7 @@
                 // Update the user list
                 writeUserListLocked();
                 updateUserIdsLocked();
+                removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
             }
         }
 
@@ -603,6 +604,17 @@
         mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
     }
 
+    private void removeDirectoryRecursive(File parent) {
+        if (parent.isDirectory()) {
+            String[] files = parent.list();
+            for (String filename : files) {
+                File child = new File(parent, filename);
+                removeDirectoryRecursive(child);
+            }
+        }
+        parent.delete();
+    }
+
     @Override
     public int getUserSerialNumber(int userHandle) {
         synchronized (mPackagesLock) {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 3373fd4..a2104bb 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -880,7 +880,8 @@
 
     private Future<Void> expectClearNotifications() throws Exception {
         final FutureAnswer future = new FutureAnswer();
-        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
+        mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt(),
+                UserHandle.myUserId());
         expectLastCall().andAnswer(future).anyTimes();
         return future;
     }
@@ -888,7 +889,7 @@
     private Future<String> expectEnqueueNotification() throws Exception {
         final FutureCapture<String> tag = new FutureCapture<String>();
         mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag.capture), anyInt(),
-                isA(Notification.class), isA(int[].class));
+                isA(Notification.class), isA(int[].class), UserHandle.myUserId());
         return tag;
     }
 
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 70e2aac..ec39aab 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -28,6 +28,7 @@
 import android.os.Environment;
 import android.os.Vibrator;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.util.Log;
 import android.net.Uri;
 import android.os.SystemClock;
@@ -798,7 +799,8 @@
                             null, 
                             100, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }
@@ -822,7 +824,8 @@
                             null, 
                             200, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }
@@ -846,7 +849,8 @@
                             null, 
                             1, 
                             n,
-                            idOut);
+                            idOut,
+                            UserHandle.myUserId());
                 } catch (android.os.RemoteException ex) {
                     // oh well
                 }