diff options
30 files changed, 443 insertions, 411 deletions
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 @@ public final class Pm { 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..b749d8e 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1052,7 +1052,7 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService } } - 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 @@ public class AccountManagerService 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); } @@ -2083,7 +2085,7 @@ public class AccountManagerService } 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService 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 @@ public class Activity extends ContextThemeWrapper 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.ApplicationInfo; 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 class ActivityManager { 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 @@ public class ActivityManager { 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM 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 @@ class ActivityManagerProxy implements IActivityManager 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 @@ class ActivityManagerProxy implements IActivityManager } 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 @@ class ActivityManagerProxy implements IActivityManager 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 @@ class ActivityManagerProxy implements IActivityManager } 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 @@ class ActivityManagerProxy implements IActivityManager 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 @@ class ActivityManagerProxy implements IActivityManager 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 @@ class ActivityManagerProxy implements IActivityManager 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 1b6f84b..408820d 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -994,7 +994,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false, - Binder.getOrigCallingUser()); + UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1007,7 +1007,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, false, false, - Binder.getOrigCallingUser()); + UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1021,7 +1021,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, true, false, - Binder.getOrigCallingUser()); + UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1054,7 +1054,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermission, - true, false, Binder.getOrigCallingUser()); + true, false, UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1125,7 +1125,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, true, - Binder.getOrigCallingUser()); + UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1158,7 +1158,7 @@ class ContextImpl extends Context { ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, - true, true, Binder.getOrigCallingUser()); + true, true, UserHandle.myUserId()); } catch (RemoteException e) { } } @@ -1173,7 +1173,7 @@ class ContextImpl extends Context { 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 interface IActivityManager extends IInterface { 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 interface IActivityManager extends IInterface { 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 interface IActivityManager extends IInterface { 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 interface IActivityManager extends IInterface { 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 @@ public interface IActivityManager extends IInterface { 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 @@ public interface IActivityManager extends IInterface { 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 @@ import android.content.Intent; /** {@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.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.Log; /** @@ -125,7 +126,27 @@ public class NotificationManager 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 @@ public class NotificationManager 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 @@ public class NotificationManager 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 @@ public final class PendingIntent implements Parcelable { 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 @@ public final class PendingIntent implements Parcelable { 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 @@ public final class PendingIntent implements Parcelable { 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 @@ public final class PendingIntent implements Parcelable { 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/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 @@ public class SyncManager implements OnAccountsUpdateListener { 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 @@ public class SyncManager implements OnAccountsUpdateListener { 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 @@ public class SyncManager implements OnAccountsUpdateListener { 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 @@ public class SyncManager implements OnAccountsUpdateListener { 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 @@ public class SyncManager implements OnAccountsUpdateListener { } 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 @@ public class SyncManager implements OnAccountsUpdateListener { } 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 @@ public class SyncManager implements OnAccountsUpdateListener { 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 class Binder implements IBinder { 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/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 @@ static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 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 @@ static const JNINativeMethod gBinderMethods[] = { /* 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/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 @@ public class BroadcastTest extends ActivityTestsBase { 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 @@ public class BroadcastTest extends ActivityTestsBase { 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/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.Context; 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 @@ public class LocationController extends BroadcastReceiver { } 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 @@ public class LocationController extends BroadcastReceiver { 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.Binder; 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 @@ class AppWidgetService extends IAppWidgetService.Stub @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 @@ class AppWidgetService extends IAppWidgetService.Stub } } - 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 @@ class AppWidgetService extends IAppWidgetService.Stub @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 @@ class AppWidgetService extends IAppWidgetService.Stub @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 @@ class AppWidgetService extends IAppWidgetService.Stub 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/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 @@ class BackupManagerService extends IBackupManager.Stub { 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_DOCUMENT; 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 class NotificationManagerService extends INotificationManager.Stub } 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 @@ public class NotificationManagerService extends INotificationManager.Stub } 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 @@ public class NotificationManagerService extends INotificationManager.Stub } 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 @@ public class NotificationManagerService extends INotificationManager.Stub // 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 @@ public class NotificationManagerService extends INotificationManager.Stub // 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 @@ public class NotificationManagerService extends INotificationManager.Stub * 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 @@ public class NotificationManagerService extends INotificationManager.Stub * {@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 @@ public class NotificationManagerService extends INotificationManager.Stub 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 @@ public class NotificationManagerService extends INotificationManager.Stub } } - /** - * 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 @@ public class NotificationManagerService extends INotificationManager.Stub } } - 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 @@ public class NotificationManagerService extends INotificationManager.Stub } // 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 @@ public class NotificationManagerService extends INotificationManager.Stub 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.Handler; 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/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 @@ class UiModeManagerService extends IUiModeManager.Stub { 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..2ddfaa2 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -776,11 +776,11 @@ class WallpaperManagerService extends IWallpaperManager.Stub { 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; 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 @@ public class ActiveServices { 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 class ActiveServices { 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 @@ public class ActiveServices { 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 @@ public class ActiveServices { } 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 @@ public class ActiveServices { 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative // 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 class ActivityManagerService extends ActivityManagerNative } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative } } + mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, + mHeavyWeightProcess.userId, 0)); mHeavyWeightProcess = null; - mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG); } } @@ -3884,8 +3870,9 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative } } - 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative } 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 @@ public final class ActivityManagerService extends ActivityManagerNative + " (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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative //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 final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative return null; } finally { if (holder != null) { - removeContentProviderExternalUnchecked(name, null); + removeContentProviderExternalUnchecked(name, null, userId); } Binder.restoreCallingIdentity(ident); } @@ -6894,8 +6885,9 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative } // 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ public final class ActivityManagerService extends ActivityManagerNative } 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 final class ActivityManagerService extends ActivityManagerNative } } + 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 @@ public final class ActivityManagerService extends ActivityManagerNative // 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 @@ final class ActivityStack { 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 @@ class PendingIntentRecord extends IIntentSender.Stub { 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 @@ class PendingIntentRecord extends IIntentSender.Stub { 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 @@ class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public class ProviderMap { } } - 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 @@ public class ProviderMap { } } - 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 @@ class ServiceRecord extends Binder { 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 @@ class ServiceRecord extends Binder { 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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/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 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { 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 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { 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.Bundle; 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 @@ public class NotificationTestList extends TestActivity null, 100, n, - idOut); + idOut, + UserHandle.myUserId()); } catch (android.os.RemoteException ex) { // oh well } @@ -822,7 +824,8 @@ public class NotificationTestList extends TestActivity null, 200, n, - idOut); + idOut, + UserHandle.myUserId()); } catch (android.os.RemoteException ex) { // oh well } @@ -846,7 +849,8 @@ public class NotificationTestList extends TestActivity null, 1, n, - idOut); + idOut, + UserHandle.myUserId()); } catch (android.os.RemoteException ex) { // oh well } |