diff --git a/core/api/current.txt b/core/api/current.txt index 229c3907e1a44..2e7e3e09ed89e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -6736,6 +6736,7 @@ package android.app { method public static void writePendingIntentOrNullToParcel(@Nullable android.app.PendingIntent, @NonNull android.os.Parcel); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT = 16777216; // 0x1000000 field public static final int FLAG_CANCEL_CURRENT = 268435456; // 0x10000000 field public static final int FLAG_IMMUTABLE = 67108864; // 0x4000000 field public static final int FLAG_MUTABLE = 33554432; // 0x2000000 diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index c58e627425b7d..dd4453114fe52 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -186,6 +186,7 @@ public final class PendingIntent implements Parcelable { FLAG_IMMUTABLE, FLAG_MUTABLE, FLAG_MUTABLE_UNAUDITED, + FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, Intent.FILL_IN_ACTION, Intent.FILL_IN_DATA, @@ -279,6 +280,21 @@ public final class PendingIntent implements Parcelable { @TestApi public static final int FLAG_MUTABLE_UNAUDITED = FLAG_MUTABLE; + /** + * Flag indicating that the created PendingIntent with {@link #FLAG_MUTABLE} + * is allowed to have an unsafe implicit Intent within.

Starting with + * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, for apps that + * target SDK {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or + * higher, creation of a PendingIntent with {@link #FLAG_MUTABLE} and an + * implicit Intent within will throw an {@link IllegalArgumentException} + * for security reasons. To bypass this check, use + * {@link #FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT} when creating a PendingIntent. + * However, it is strongly recommended to not to use this flag and make the + * Intent explicit or the PendingIntent immutable, thereby making the Intent + * safe. + */ + public static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT = 1<<24; + /** * Exception thrown when trying to send through a PendingIntent that * has been canceled or is otherwise no longer able to execute the request. @@ -418,12 +434,13 @@ public final class PendingIntent implements Parcelable { // This will be changed to a throw of an exception on the server side once we finish // migrating to safer PendingIntents b/262253127. // - Otherwise, warn that it will be blocked from target SDK U. - if (isNewMutableImplicitPendingIntent(flags, intent)) { + if (isNewMutableDisallowedImplicitPendingIntent(flags, intent)) { if (Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) { String msg = packageName + ": Targeting U+ (version " + Build.VERSION_CODES.UPSIDE_DOWN_CAKE + " and above) disallows" + " creating or retrieving a PendingIntent with FLAG_MUTABLE," - + " an implicit Intent within and without FLAG_NO_CREATE for" + + " an implicit Intent within and without FLAG_NO_CREATE and" + + " FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for" + " security reasons. To retrieve an already existing" + " PendingIntent, use FLAG_NO_CREATE, however, to create a" + " new PendingIntent with an implicit Intent use" @@ -441,11 +458,15 @@ public final class PendingIntent implements Parcelable { } /** @hide */ - public static boolean isNewMutableImplicitPendingIntent(int flags, @NonNull Intent intent) { + public static boolean isNewMutableDisallowedImplicitPendingIntent(int flags, + @NonNull Intent intent) { boolean isFlagNoCreateSet = (flags & PendingIntent.FLAG_NO_CREATE) != 0; boolean isFlagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; boolean isImplicit = (intent.getComponent() == null) && (intent.getPackage() == null); - return !isFlagNoCreateSet && isFlagMutableSet && isImplicit; + boolean isFlagAllowUnsafeImplicitIntentSet = + (flags & PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT) != 0; + return !isFlagNoCreateSet && isFlagMutableSet && isImplicit + && !isFlagAllowUnsafeImplicitIntentSet; } /**