Loading core/java/android/app/ActivityManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,14 @@ public abstract class ActivityManagerInternal { @Nullable public abstract Intent getIntentForIntentSender(IIntentSender sender); /** * Effectively PendingIntent.getActivityForUser(), but the PendingIntent is * owned by the given uid rather than by the caller (i.e. the system). */ public abstract PendingIntent getPendingIntentActivityAsApp( int requestCode, @NonNull Intent intent, int flags, Bundle options, String ownerPkgName, int ownerUid); /** * @return mBootTimeTempAllowlistDuration of ActivityManagerConstants. */ Loading core/java/android/app/PendingIntent.java +6 −6 Original line number Diff line number Diff line Loading @@ -358,12 +358,6 @@ public final class PendingIntent implements Parcelable { private static void checkFlags(int flags, String packageName) { final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0; final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S + " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE" + " be specified when creating a PendingIntent.\nStrongly consider" + " using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality" + " depends on the PendingIntent being mutable, e.g. if it needs to" + " be used with inline replies or bubbles."; if (flagImmutableSet && flagMutableSet) { throw new IllegalArgumentException( Loading @@ -372,6 +366,12 @@ public final class PendingIntent implements Parcelable { if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED) && !flagImmutableSet && !flagMutableSet) { String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S + " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE" + " be specified when creating a PendingIntent.\nStrongly consider" + " using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality" + " depends on the PendingIntent being mutable, e.g. if it needs to" + " be used with inline replies or bubbles."; throw new IllegalArgumentException(msg); } } Loading services/core/java/com/android/server/am/ActivityManagerService.java +55 −12 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART; import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_TOP; Loading Loading @@ -4815,10 +4816,27 @@ public class ActivityManagerService extends IActivityManager.Stub public IIntentSender getIntentSenderWithFeature(int type, String packageName, String featureId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions, int userId) { enforceNotIsolatedCaller("getIntentSender"); return getIntentSenderWithFeatureAsApp(type, packageName, featureId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions, userId, Binder.getCallingUid()); } /** * System-internal callers can invoke this with owningUid being the app's own identity * rather than the public API's behavior of always assigning ownership to the actual * caller identity. This will create an IntentSender as though the package/userid/uid app * were the caller, so that the ultimate PendingIntent is triggered with only the app's * capabilities and not the system's. Used in cases like notification groups where * the OS must synthesize a PendingIntent on an app's behalf. */ public IIntentSender getIntentSenderWithFeatureAsApp(int type, String packageName, String featureId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions, int userId, int owningUid) { // NOTE: The service lock isn't held in this method because nothing in the method requires // the service lock to be held. enforceNotIsolatedCaller("getIntentSender"); // Refuse possible leaked file descriptors if (intents != null) { if (intents.length < 1) { Loading Loading @@ -4849,9 +4867,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } int callingUid = Binder.getCallingUid(); int origUserId = userId; userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, userId = mUserController.handleIncomingUser(Binder.getCallingPid(), owningUid, userId, type == ActivityManager.INTENT_SENDER_BROADCAST, ALLOW_NON_FULL, "getIntentSender", null); if (origUserId == UserHandle.USER_CURRENT) { Loading @@ -4861,13 +4878,13 @@ public class ActivityManagerService extends IActivityManager.Stub userId = UserHandle.USER_CURRENT; } try { if (callingUid != 0 && callingUid != SYSTEM_UID) { if (owningUid != 0 && owningUid != SYSTEM_UID) { final int uid = AppGlobals.getPackageManager().getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid)); if (!UserHandle.isSameApp(callingUid, uid)) { MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(owningUid)); if (!UserHandle.isSameApp(owningUid, uid)) { String msg = "Permission Denial: getIntentSender() from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + ", uid=" + owningUid + ", (need uid=" + uid + ")" + " is not allowed to send as package " + packageName; Slog.w(TAG, msg); Loading @@ -4876,12 +4893,12 @@ public class ActivityManagerService extends IActivityManager.Stub } if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) { return mAtmInternal.getIntentSender(type, packageName, featureId, callingUid, return mAtmInternal.getIntentSender(type, packageName, featureId, owningUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions); } return mPendingIntentController.getIntentSender(type, packageName, featureId, callingUid, userId, token, resultWho, requestCode, intents, resolvedTypes, owningUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions); } catch (RemoteException e) { throw new SecurityException(e); Loading Loading @@ -16058,6 +16075,32 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.getIntentForIntentSender(sender); } @Override public PendingIntent getPendingIntentActivityAsApp( int requestCode, @NonNull Intent intent, int flags, Bundle options, String ownerPkg, int ownerUid) { // system callers must explicitly set mutability state final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0; final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; if (flagImmutableSet == flagMutableSet) { throw new IllegalArgumentException( "Must set exactly one of FLAG_IMMUTABLE or FLAG_MUTABLE"); } final Context context = ActivityManagerService.this.mContext; String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver()); intent.migrateExtraStreamToClipData(context); intent.prepareToLeaveProcess(context); IIntentSender target = ActivityManagerService.this.getIntentSenderWithFeatureAsApp( INTENT_SENDER_ACTIVITY, ownerPkg, context.getAttributionTag(), null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, flags, options, UserHandle.getUserId(ownerUid), ownerUid); return target != null ? new PendingIntent(target) : null; } @Override public long getBootTimeTempAllowListDuration() { // Do not lock ActivityManagerService.this here, this API is called by services/core/java/com/android/server/notification/NotificationManagerService.java +5 −3 Original line number Diff line number Diff line Loading @@ -5677,9 +5677,11 @@ public class NotificationManagerService extends SystemService { summaryNotification.extras.putAll(extras); Intent appIntent = getContext().getPackageManager().getLaunchIntentForPackage(pkg); if (appIntent != null) { summaryNotification.contentIntent = PendingIntent.getActivityAsUser( getContext(), 0, appIntent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.of(userId)); final ActivityManagerInternal ami = LocalServices .getService(ActivityManagerInternal.class); summaryNotification.contentIntent = ami.getPendingIntentActivityAsApp( 0, appIntent, PendingIntent.FLAG_IMMUTABLE, null, pkg, appInfo.uid); } final StatusBarNotification summarySbn = new StatusBarNotification(adjustedSbn.getPackageName(), Loading Loading
core/java/android/app/ActivityManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,14 @@ public abstract class ActivityManagerInternal { @Nullable public abstract Intent getIntentForIntentSender(IIntentSender sender); /** * Effectively PendingIntent.getActivityForUser(), but the PendingIntent is * owned by the given uid rather than by the caller (i.e. the system). */ public abstract PendingIntent getPendingIntentActivityAsApp( int requestCode, @NonNull Intent intent, int flags, Bundle options, String ownerPkgName, int ownerUid); /** * @return mBootTimeTempAllowlistDuration of ActivityManagerConstants. */ Loading
core/java/android/app/PendingIntent.java +6 −6 Original line number Diff line number Diff line Loading @@ -358,12 +358,6 @@ public final class PendingIntent implements Parcelable { private static void checkFlags(int flags, String packageName) { final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0; final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S + " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE" + " be specified when creating a PendingIntent.\nStrongly consider" + " using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality" + " depends on the PendingIntent being mutable, e.g. if it needs to" + " be used with inline replies or bubbles."; if (flagImmutableSet && flagMutableSet) { throw new IllegalArgumentException( Loading @@ -372,6 +366,12 @@ public final class PendingIntent implements Parcelable { if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED) && !flagImmutableSet && !flagMutableSet) { String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S + " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE" + " be specified when creating a PendingIntent.\nStrongly consider" + " using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality" + " depends on the PendingIntent being mutable, e.g. if it needs to" + " be used with inline replies or bubbles."; throw new IllegalArgumentException(msg); } } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +55 −12 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.ActivityManager.INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_ISOLATED_STORAGE; import static android.app.ActivityManager.INSTR_FLAG_DISABLE_TEST_API_CHECKS; import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART; import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_TOP; Loading Loading @@ -4815,10 +4816,27 @@ public class ActivityManagerService extends IActivityManager.Stub public IIntentSender getIntentSenderWithFeature(int type, String packageName, String featureId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions, int userId) { enforceNotIsolatedCaller("getIntentSender"); return getIntentSenderWithFeatureAsApp(type, packageName, featureId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions, userId, Binder.getCallingUid()); } /** * System-internal callers can invoke this with owningUid being the app's own identity * rather than the public API's behavior of always assigning ownership to the actual * caller identity. This will create an IntentSender as though the package/userid/uid app * were the caller, so that the ultimate PendingIntent is triggered with only the app's * capabilities and not the system's. Used in cases like notification groups where * the OS must synthesize a PendingIntent on an app's behalf. */ public IIntentSender getIntentSenderWithFeatureAsApp(int type, String packageName, String featureId, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, int flags, Bundle bOptions, int userId, int owningUid) { // NOTE: The service lock isn't held in this method because nothing in the method requires // the service lock to be held. enforceNotIsolatedCaller("getIntentSender"); // Refuse possible leaked file descriptors if (intents != null) { if (intents.length < 1) { Loading Loading @@ -4849,9 +4867,8 @@ public class ActivityManagerService extends IActivityManager.Stub } } int callingUid = Binder.getCallingUid(); int origUserId = userId; userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, userId = mUserController.handleIncomingUser(Binder.getCallingPid(), owningUid, userId, type == ActivityManager.INTENT_SENDER_BROADCAST, ALLOW_NON_FULL, "getIntentSender", null); if (origUserId == UserHandle.USER_CURRENT) { Loading @@ -4861,13 +4878,13 @@ public class ActivityManagerService extends IActivityManager.Stub userId = UserHandle.USER_CURRENT; } try { if (callingUid != 0 && callingUid != SYSTEM_UID) { if (owningUid != 0 && owningUid != SYSTEM_UID) { final int uid = AppGlobals.getPackageManager().getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid)); if (!UserHandle.isSameApp(callingUid, uid)) { MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(owningUid)); if (!UserHandle.isSameApp(owningUid, uid)) { String msg = "Permission Denial: getIntentSender() from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + ", uid=" + owningUid + ", (need uid=" + uid + ")" + " is not allowed to send as package " + packageName; Slog.w(TAG, msg); Loading @@ -4876,12 +4893,12 @@ public class ActivityManagerService extends IActivityManager.Stub } if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) { return mAtmInternal.getIntentSender(type, packageName, featureId, callingUid, return mAtmInternal.getIntentSender(type, packageName, featureId, owningUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions); } return mPendingIntentController.getIntentSender(type, packageName, featureId, callingUid, userId, token, resultWho, requestCode, intents, resolvedTypes, owningUid, userId, token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions); } catch (RemoteException e) { throw new SecurityException(e); Loading Loading @@ -16058,6 +16075,32 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.getIntentForIntentSender(sender); } @Override public PendingIntent getPendingIntentActivityAsApp( int requestCode, @NonNull Intent intent, int flags, Bundle options, String ownerPkg, int ownerUid) { // system callers must explicitly set mutability state final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0; final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; if (flagImmutableSet == flagMutableSet) { throw new IllegalArgumentException( "Must set exactly one of FLAG_IMMUTABLE or FLAG_MUTABLE"); } final Context context = ActivityManagerService.this.mContext; String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver()); intent.migrateExtraStreamToClipData(context); intent.prepareToLeaveProcess(context); IIntentSender target = ActivityManagerService.this.getIntentSenderWithFeatureAsApp( INTENT_SENDER_ACTIVITY, ownerPkg, context.getAttributionTag(), null, null, requestCode, new Intent[] { intent }, resolvedType != null ? new String[] { resolvedType } : null, flags, options, UserHandle.getUserId(ownerUid), ownerUid); return target != null ? new PendingIntent(target) : null; } @Override public long getBootTimeTempAllowListDuration() { // Do not lock ActivityManagerService.this here, this API is called by
services/core/java/com/android/server/notification/NotificationManagerService.java +5 −3 Original line number Diff line number Diff line Loading @@ -5677,9 +5677,11 @@ public class NotificationManagerService extends SystemService { summaryNotification.extras.putAll(extras); Intent appIntent = getContext().getPackageManager().getLaunchIntentForPackage(pkg); if (appIntent != null) { summaryNotification.contentIntent = PendingIntent.getActivityAsUser( getContext(), 0, appIntent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.of(userId)); final ActivityManagerInternal ami = LocalServices .getService(ActivityManagerInternal.class); summaryNotification.contentIntent = ami.getPendingIntentActivityAsApp( 0, appIntent, PendingIntent.FLAG_IMMUTABLE, null, pkg, appInfo.uid); } final StatusBarNotification summarySbn = new StatusBarNotification(adjustedSbn.getPackageName(), Loading