Define FLAG_MUTABLE and add a compat change for explicit definition of PendingIntent mutability flags
For future releases, we will require that either FLAG_IMMUTABLE or FLAG_MUTABLE is defined when a PendingIntent is created. The check only results in a log.wtf for now while we notify, identify, and update major PendingIntents. We will add a stricter IllegalArgumentException soon. - Define FLAG_MUTABLE - Add a check and log.wtf that either FLAG_IMMUTABLE or FLAG_MUTABLE is specified on creation for future releases - Update api/current.txt and non-updatable-api/current.txt to include FLAG_MUTABLE Test: atest PendingIntentTest Bug: 160794467 Change-Id: I1f1f72c6ce22358e98e9f38be2fb98b27e60898c
This commit is contained in:
@@ -6138,6 +6138,7 @@ package android.app {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.app.PendingIntent> CREATOR;
|
||||
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
|
||||
field public static final int FLAG_NO_CREATE = 536870912; // 0x20000000
|
||||
field public static final int FLAG_ONE_SHOT = 1073741824; // 0x40000000
|
||||
field public static final int FLAG_UPDATE_CURRENT = 134217728; // 0x8000000
|
||||
|
||||
@@ -19,12 +19,16 @@ package android.app;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.compat.Compatibility;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledAfter;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -35,6 +39,7 @@ import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.AndroidException;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
@@ -102,11 +107,20 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* FLAG_ONE_SHOT, <b>both</b> FLAG_ONE_SHOT and FLAG_NO_CREATE need to be supplied.
|
||||
*/
|
||||
public final class PendingIntent implements Parcelable {
|
||||
private static final String TAG = "PendingIntent";
|
||||
private final IIntentSender mTarget;
|
||||
private IResultReceiver mCancelReceiver;
|
||||
private IBinder mWhitelistToken;
|
||||
private ArraySet<CancelListener> mCancelListeners;
|
||||
|
||||
/**
|
||||
* It is now required to specify either {@link #FLAG_IMMUTABLE}
|
||||
* or {@link #FLAG_MUTABLE} when creating a PendingIntent.
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R)
|
||||
static final long PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED = 160794467L;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(flag = true,
|
||||
value = {
|
||||
@@ -115,6 +129,7 @@ public final class PendingIntent implements Parcelable {
|
||||
FLAG_CANCEL_CURRENT,
|
||||
FLAG_UPDATE_CURRENT,
|
||||
FLAG_IMMUTABLE,
|
||||
FLAG_MUTABLE,
|
||||
|
||||
Intent.FILL_IN_ACTION,
|
||||
Intent.FILL_IN_DATA,
|
||||
@@ -174,6 +189,20 @@ public final class PendingIntent implements Parcelable {
|
||||
*/
|
||||
public static final int FLAG_IMMUTABLE = 1<<26;
|
||||
|
||||
/**
|
||||
* Flag indicating that the created PendingIntent should be mutable.
|
||||
* This flag cannot be combined with {@link #FLAG_IMMUTABLE}. <p>Up until
|
||||
* {@link android.os.Build.VERSION_CODES#R}, PendingIntents are assumed to
|
||||
* be mutable by default, unless {@link #FLAG_IMMUTABLE} is set. Starting
|
||||
* with {@link android.os.Build.VERSION_CODES#S}, it will be required to
|
||||
* explicitly specify the mutability of PendingIntents on creation with
|
||||
* either (@link #FLAG_IMMUTABLE} or {@link #FLAG_MUTABLE}. It is strongly
|
||||
* recommended to use {@link #FLAG_IMMUTABLE} when creating a
|
||||
* PendingIntent. {@link #FLAG_MUTABLE} should only be used when some
|
||||
* functionality relies on modifying the underlying intent.
|
||||
*/
|
||||
public static final int FLAG_MUTABLE = 1<<25;
|
||||
|
||||
/**
|
||||
* Exception thrown when trying to send through a PendingIntent that
|
||||
* has been canceled or is otherwise no longer able to execute the request.
|
||||
@@ -286,6 +315,23 @@ public final class PendingIntent implements Parcelable {
|
||||
sOnMarshaledListener.set(listener);
|
||||
}
|
||||
|
||||
private static void checkFlags(int flags, String packageName) {
|
||||
final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0;
|
||||
final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0;
|
||||
|
||||
if (flagImmutableSet && flagMutableSet) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot set both FLAG_IMMUTABLE and FLAG_MUTABLE for PendingIntent");
|
||||
}
|
||||
|
||||
if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED)
|
||||
&& !flagImmutableSet && !flagMutableSet) {
|
||||
Log.wtf(TAG, 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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a PendingIntent that will start a new activity, like calling
|
||||
* {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
|
||||
@@ -350,6 +396,7 @@ public final class PendingIntent implements Parcelable {
|
||||
String packageName = context.getPackageName();
|
||||
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
|
||||
context.getContentResolver()) : null;
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
intent.migrateExtraStreamToClipData(context);
|
||||
intent.prepareToLeaveProcess(context);
|
||||
@@ -376,6 +423,7 @@ public final class PendingIntent implements Parcelable {
|
||||
String packageName = context.getPackageName();
|
||||
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
|
||||
context.getContentResolver()) : null;
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
intent.migrateExtraStreamToClipData(context);
|
||||
intent.prepareToLeaveProcess(context);
|
||||
@@ -495,6 +543,7 @@ public final class PendingIntent implements Parcelable {
|
||||
intents[i].prepareToLeaveProcess(context);
|
||||
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
|
||||
}
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
IIntentSender target =
|
||||
ActivityManager.getService().getIntentSenderWithFeature(
|
||||
@@ -521,6 +570,7 @@ public final class PendingIntent implements Parcelable {
|
||||
intents[i].prepareToLeaveProcess(context);
|
||||
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
|
||||
}
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
IIntentSender target =
|
||||
ActivityManager.getService().getIntentSenderWithFeature(
|
||||
@@ -572,6 +622,7 @@ public final class PendingIntent implements Parcelable {
|
||||
String packageName = context.getPackageName();
|
||||
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
|
||||
context.getContentResolver()) : null;
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
intent.prepareToLeaveProcess(context);
|
||||
IIntentSender target =
|
||||
@@ -651,6 +702,7 @@ public final class PendingIntent implements Parcelable {
|
||||
String packageName = context.getPackageName();
|
||||
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
|
||||
context.getContentResolver()) : null;
|
||||
checkFlags(flags, packageName);
|
||||
try {
|
||||
intent.prepareToLeaveProcess(context);
|
||||
IIntentSender target =
|
||||
|
||||
@@ -6138,6 +6138,7 @@ package android.app {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.app.PendingIntent> CREATOR;
|
||||
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
|
||||
field public static final int FLAG_NO_CREATE = 536870912; // 0x20000000
|
||||
field public static final int FLAG_ONE_SHOT = 1073741824; // 0x40000000
|
||||
field public static final int FLAG_UPDATE_CURRENT = 134217728; // 0x8000000
|
||||
|
||||
Reference in New Issue
Block a user