summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityManagerInternal.java8
-rw-r--r--core/java/android/app/PendingIntent.java12
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java67
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java8
4 files changed, 74 insertions, 21 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 080352408a67..605340061994 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -561,6 +561,14 @@ public abstract class ActivityManagerInternal {
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.
*/
public abstract long getBootTimeTempAllowListDuration();
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index ca0868310dee..0136a35e3975 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -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(
@@ -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);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4b640a61f1dd..ded66d5dc135 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -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;
@@ -4814,10 +4815,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) {
@@ -4848,9 +4866,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) {
@@ -4860,27 +4877,27 @@ 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()
- + ", (need uid=" + uid + ")"
- + " is not allowed to send as package " + packageName;
+ + Binder.getCallingPid()
+ + ", uid=" + owningUid
+ + ", (need uid=" + uid + ")"
+ + " is not allowed to send as package " + packageName;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
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);
@@ -16064,6 +16081,32 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@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
// PackageManagerService.
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 52a5dc1e8982..ef6f11ae7dbf 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5680,9 +5680,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(),