1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app; 18 19 import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY; 20 import static android.app.ActivityManager.INTENT_SENDER_BROADCAST; 21 import static android.app.ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE; 22 import static android.app.ActivityManager.INTENT_SENDER_SERVICE; 23 24 import android.Manifest.permission; 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SystemApi; 30 import android.annotation.SystemApi.Client; 31 import android.annotation.TestApi; 32 import android.app.ActivityManager.PendingIntentInfo; 33 import android.compat.Compatibility; 34 import android.compat.annotation.ChangeId; 35 import android.compat.annotation.EnabledAfter; 36 import android.compat.annotation.EnabledSince; 37 import android.compat.annotation.Overridable; 38 import android.compat.annotation.UnsupportedAppUsage; 39 import android.content.Context; 40 import android.content.IIntentReceiver; 41 import android.content.IIntentSender; 42 import android.content.Intent; 43 import android.content.IntentSender; 44 import android.content.pm.PackageManager.ResolveInfoFlagsBits; 45 import android.content.pm.ParceledListSlice; 46 import android.content.pm.ResolveInfo; 47 import android.os.Build; 48 import android.os.Bundle; 49 import android.os.Handler; 50 import android.os.IBinder; 51 import android.os.Looper; 52 import android.os.Parcel; 53 import android.os.Parcelable; 54 import android.os.RemoteException; 55 import android.os.UserHandle; 56 import android.util.AndroidException; 57 import android.util.ArraySet; 58 import android.util.Log; 59 import android.util.Pair; 60 import android.util.proto.ProtoOutputStream; 61 62 import com.android.internal.annotations.GuardedBy; 63 import com.android.internal.os.IResultReceiver; 64 65 import java.lang.annotation.Retention; 66 import java.lang.annotation.RetentionPolicy; 67 import java.util.ArrayList; 68 import java.util.Collections; 69 import java.util.List; 70 import java.util.Objects; 71 import java.util.concurrent.Executor; 72 73 /** 74 * A description of an Intent and target action to perform with it. Instances 75 * of this class are created with {@link #getActivity}, {@link #getActivities}, 76 * {@link #getBroadcast}, and {@link #getService}; the returned object can be 77 * handed to other applications so that they can perform the action you 78 * described on your behalf at a later time. 79 * 80 * <p>By giving a PendingIntent to another application, 81 * you are granting it the right to perform the operation you have specified 82 * as if the other application was yourself (with the same permissions and 83 * identity). As such, you should be careful about how you build the PendingIntent: 84 * almost always, for example, the base Intent you supply should have the component 85 * name explicitly set to one of your own components, to ensure it is ultimately 86 * sent there and nowhere else. 87 * 88 * <p>A PendingIntent itself is simply a reference to a token maintained by 89 * the system describing the original data used to retrieve it. This means 90 * that, even if its owning application's process is killed, the 91 * PendingIntent itself will remain usable from other processes that 92 * have been given it. If the creating application later re-retrieves the 93 * same kind of PendingIntent (same operation, same Intent action, data, 94 * categories, and components, and same flags), it will receive a PendingIntent 95 * representing the same token if that is still valid, and can thus call 96 * {@link #cancel} to remove it. 97 * 98 * <p>Because of this behavior, it is important to know when two Intents 99 * are considered to be the same for purposes of retrieving a PendingIntent. 100 * A common mistake people make is to create multiple PendingIntent objects 101 * with Intents that only vary in their "extra" contents, expecting to get 102 * a different PendingIntent each time. This does <em>not</em> happen. The 103 * parts of the Intent that are used for matching are the same ones defined 104 * by {@link Intent#filterEquals(Intent) Intent.filterEquals}. If you use two 105 * Intent objects that are equivalent as per 106 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get 107 * the same PendingIntent for both of them. 108 * 109 * <p>There are two typical ways to deal with this. 110 * 111 * <p>If you truly need multiple distinct PendingIntent objects active at 112 * the same time (such as to use as two notifications that are both shown 113 * at the same time), then you will need to ensure there is something that 114 * is different about them to associate them with different PendingIntents. 115 * This may be any of the Intent attributes considered by 116 * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different 117 * request code integers supplied to {@link #getActivity}, {@link #getActivities}, 118 * {@link #getBroadcast}, or {@link #getService}. 119 * 120 * <p>If you only need one PendingIntent active at a time for any of the 121 * Intents you will use, then you can alternatively use the flags 122 * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either 123 * cancel or modify whatever current PendingIntent is associated with the 124 * Intent you are supplying. 125 * 126 * <p>Also note that flags like {@link #FLAG_ONE_SHOT} or {@link #FLAG_IMMUTABLE} describe the 127 * PendingIntent instance and thus, are used to identify it. Any calls to retrieve or modify a 128 * PendingIntent created with these flags will also require these flags to be supplied in 129 * conjunction with others. E.g. To retrieve an existing PendingIntent created with 130 * FLAG_ONE_SHOT, <b>both</b> FLAG_ONE_SHOT and FLAG_NO_CREATE need to be supplied. 131 */ 132 public final class PendingIntent implements Parcelable { 133 private static final String TAG = "PendingIntent"; 134 @NonNull 135 private final IIntentSender mTarget; 136 private IBinder mWhitelistToken; 137 138 // cached pending intent information 139 private @Nullable PendingIntentInfo mCachedInfo; 140 141 /** 142 * Structure to store information related to {@link #addCancelListener}, which is rarely used, 143 * so we lazily allocate it to keep the PendingIntent class size small. 144 */ 145 private final class CancelListerInfo extends IResultReceiver.Stub { 146 private final ArraySet<Pair<Executor, CancelListener>> mCancelListeners = new ArraySet<>(); 147 148 /** 149 * Whether the PI is canceled or not. Note this is essentially a "cache" that's updated 150 * only when the client uses {@link #addCancelListener}. Even if this is false, that 151 * still doesn't know the PI is *not* canceled, but if it's true, this PI is definitely 152 * canceled. 153 */ 154 private boolean mCanceled; 155 156 @Override send(int resultCode, Bundle resultData)157 public void send(int resultCode, Bundle resultData) throws RemoteException { 158 notifyCancelListeners(); 159 } 160 } 161 162 @GuardedBy("mTarget") 163 private @Nullable CancelListerInfo mCancelListerInfo; 164 165 /** 166 * It is now required to specify either {@link #FLAG_IMMUTABLE} 167 * or {@link #FLAG_MUTABLE} when creating a PendingIntent. 168 */ 169 @ChangeId 170 @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R) 171 static final long PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED = 160794467L; 172 173 /** @hide */ 174 @ChangeId 175 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 176 @Overridable 177 public static final long BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT = 236704164L; 178 179 /** @hide */ 180 @IntDef(flag = true, 181 value = { 182 FLAG_ONE_SHOT, 183 FLAG_NO_CREATE, 184 FLAG_CANCEL_CURRENT, 185 FLAG_UPDATE_CURRENT, 186 FLAG_IMMUTABLE, 187 FLAG_MUTABLE, 188 FLAG_MUTABLE_UNAUDITED, 189 FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT, 190 191 Intent.FILL_IN_ACTION, 192 Intent.FILL_IN_DATA, 193 Intent.FILL_IN_CATEGORIES, 194 Intent.FILL_IN_COMPONENT, 195 Intent.FILL_IN_PACKAGE, 196 Intent.FILL_IN_SOURCE_BOUNDS, 197 Intent.FILL_IN_SELECTOR, 198 Intent.FILL_IN_CLIP_DATA 199 }) 200 @Retention(RetentionPolicy.SOURCE) 201 public @interface Flags {} 202 203 /** 204 * Flag indicating that this PendingIntent can be used only once. 205 * For use with {@link #getActivity}, {@link #getBroadcast}, and 206 * {@link #getService}. <p>If set, after 207 * {@link #send()} is called on it, it will be automatically 208 * canceled for you and any future attempt to send through it will fail. 209 */ 210 public static final int FLAG_ONE_SHOT = 1<<30; 211 /** 212 * Flag indicating that if the described PendingIntent does not 213 * already exist, then simply return null instead of creating it. 214 * For use with {@link #getActivity}, {@link #getBroadcast}, and 215 * {@link #getService}. 216 */ 217 public static final int FLAG_NO_CREATE = 1<<29; 218 /** 219 * Flag indicating that if the described PendingIntent already exists, 220 * the current one should be canceled before generating a new one. 221 * For use with {@link #getActivity}, {@link #getBroadcast}, and 222 * {@link #getService}. <p>You can use 223 * this to retrieve a new PendingIntent when you are only changing the 224 * extra data in the Intent; by canceling the previous pending intent, 225 * this ensures that only entities given the new data will be able to 226 * launch it. If this assurance is not an issue, consider 227 * {@link #FLAG_UPDATE_CURRENT}. 228 */ 229 public static final int FLAG_CANCEL_CURRENT = 1<<28; 230 /** 231 * Flag indicating that if the described PendingIntent already exists, 232 * then keep it but replace its extra data with what is in this new 233 * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and 234 * {@link #getService}. <p>This can be used if you are creating intents where only the 235 * extras change, and don't care that any entities that received your 236 * previous PendingIntent will be able to launch it with your new 237 * extras even if they are not explicitly given to it. 238 * 239 * <p>{@link #FLAG_UPDATE_CURRENT} still works even if {@link 240 * #FLAG_IMMUTABLE} is set - the creator of the PendingIntent can always 241 * update the PendingIntent itself. The IMMUTABLE flag only limits the 242 * ability to alter the semantics of the intent that is sent by {@link 243 * #send} by the invoker of {@link #send}. 244 */ 245 public static final int FLAG_UPDATE_CURRENT = 1<<27; 246 247 /** 248 * Flag indicating that the created PendingIntent should be immutable. 249 * This means that the additional intent argument passed to the send 250 * methods to fill in unpopulated properties of this intent will be 251 * ignored. 252 * 253 * <p>{@link #FLAG_IMMUTABLE} only limits the ability to alter the 254 * semantics of the intent that is sent by {@link #send} by the invoker of 255 * {@link #send}. The creator of the PendingIntent can always update the 256 * PendingIntent itself via {@link #FLAG_UPDATE_CURRENT}. 257 */ 258 public static final int FLAG_IMMUTABLE = 1<<26; 259 260 /** 261 * Flag indicating that the created PendingIntent should be mutable. 262 * This flag cannot be combined with {@link #FLAG_IMMUTABLE}. <p>Up until 263 * {@link android.os.Build.VERSION_CODES#R}, PendingIntents are assumed to 264 * be mutable by default, unless {@link #FLAG_IMMUTABLE} is set. Starting 265 * with {@link android.os.Build.VERSION_CODES#S}, it will be required to 266 * explicitly specify the mutability of PendingIntents on creation with 267 * either (@link #FLAG_IMMUTABLE} or {@link #FLAG_MUTABLE}. It is strongly 268 * recommended to use {@link #FLAG_IMMUTABLE} when creating a 269 * PendingIntent. {@link #FLAG_MUTABLE} should only be used when some 270 * functionality relies on modifying the underlying intent, e.g. any 271 * PendingIntent that needs to be used with inline reply or bubbles. 272 */ 273 public static final int FLAG_MUTABLE = 1<<25; 274 275 /** 276 * @deprecated Use {@link #FLAG_IMMUTABLE} or {@link #FLAG_MUTABLE} instead. 277 * @hide 278 */ 279 @Deprecated 280 @TestApi 281 public static final int FLAG_MUTABLE_UNAUDITED = FLAG_MUTABLE; 282 283 /** 284 * Flag indicating that the created PendingIntent with {@link #FLAG_MUTABLE} 285 * is allowed to have an unsafe implicit Intent within. <p>Starting with 286 * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, for apps that 287 * target SDK {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or 288 * higher, creation of a PendingIntent with {@link #FLAG_MUTABLE} and an 289 * implicit Intent within will throw an {@link IllegalArgumentException} 290 * for security reasons. To bypass this check, use 291 * {@link #FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT} when creating a PendingIntent. 292 * However, it is strongly recommended to not to use this flag and make the 293 * Intent explicit or the PendingIntent immutable, thereby making the Intent 294 * safe. 295 */ 296 public static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT = 1<<24; 297 298 /** 299 * Exception thrown when trying to send through a PendingIntent that 300 * has been canceled or is otherwise no longer able to execute the request. 301 */ 302 public static class CanceledException extends AndroidException { CanceledException()303 public CanceledException() { 304 } 305 CanceledException(String name)306 public CanceledException(String name) { 307 super(name); 308 } 309 CanceledException(Exception cause)310 public CanceledException(Exception cause) { 311 super(cause); 312 } 313 } 314 315 /** 316 * Callback interface for discovering when a send operation has 317 * completed. Primarily for use with a PendingIntent that is 318 * performing a broadcast, this provides the same information as 319 * calling {@link Context#sendOrderedBroadcast(Intent, String, 320 * android.content.BroadcastReceiver, Handler, int, String, Bundle) 321 * Context.sendBroadcast()} with a final BroadcastReceiver. 322 */ 323 public interface OnFinished { 324 /** 325 * Called when a send operation as completed. 326 * 327 * @param pendingIntent The PendingIntent this operation was sent through. 328 * @param intent The original Intent that was sent. 329 * @param resultCode The final result code determined by the send. 330 * @param resultData The final data collected by a broadcast. 331 * @param resultExtras The final extras collected by a broadcast. 332 */ onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)333 void onSendFinished(PendingIntent pendingIntent, Intent intent, 334 int resultCode, String resultData, Bundle resultExtras); 335 } 336 337 private static class FinishedDispatcher extends IIntentReceiver.Stub 338 implements Runnable { 339 private final PendingIntent mPendingIntent; 340 private final OnFinished mWho; 341 private final Handler mHandler; 342 private Intent mIntent; 343 private int mResultCode; 344 private String mResultData; 345 private Bundle mResultExtras; 346 private static Handler sDefaultSystemHandler; FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler)347 FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) { 348 mPendingIntent = pi; 349 mWho = who; 350 if (handler == null && ActivityThread.isSystem()) { 351 // We assign a default handler for the system process to avoid deadlocks when 352 // processing receivers in various components that hold global service locks. 353 if (sDefaultSystemHandler == null) { 354 sDefaultSystemHandler = new Handler(Looper.getMainLooper()); 355 } 356 mHandler = sDefaultSystemHandler; 357 } else { 358 mHandler = handler; 359 } 360 } performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean serialized, boolean sticky, int sendingUser)361 public void performReceive(Intent intent, int resultCode, String data, 362 Bundle extras, boolean serialized, boolean sticky, int sendingUser) { 363 mIntent = intent; 364 mResultCode = resultCode; 365 mResultData = data; 366 mResultExtras = extras; 367 if (mHandler == null) { 368 run(); 369 } else { 370 mHandler.post(this); 371 } 372 } run()373 public void run() { 374 mWho.onSendFinished(mPendingIntent, mIntent, mResultCode, 375 mResultData, mResultExtras); 376 } 377 } 378 379 /** 380 * Listener for observing when pending intents are written to a parcel. 381 * 382 * @hide 383 */ 384 public interface OnMarshaledListener { 385 /** 386 * Called when a pending intent is written to a parcel. 387 * 388 * @param intent The pending intent. 389 * @param parcel The parcel to which it was written. 390 * @param flags The parcel flags when it was written. 391 */ onMarshaled(PendingIntent intent, Parcel parcel, int flags)392 void onMarshaled(PendingIntent intent, Parcel parcel, int flags); 393 } 394 395 private static final ThreadLocal<List<OnMarshaledListener>> sOnMarshaledListener = 396 ThreadLocal.withInitial(ArrayList::new); 397 398 /** 399 * Registers an listener for pending intents being written to a parcel. This replaces any 400 * listeners previously added. 401 * 402 * @param listener The listener, null to clear. 403 * 404 * @hide 405 */ 406 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setOnMarshaledListener(OnMarshaledListener listener)407 public static void setOnMarshaledListener(OnMarshaledListener listener) { 408 final List<OnMarshaledListener> listeners = sOnMarshaledListener.get(); 409 listeners.clear(); 410 if (listener != null) { 411 listeners.add(listener); 412 } 413 } 414 415 /** 416 * Adds a listener for pending intents being written to a parcel. 417 * @hide 418 */ addOnMarshaledListener(OnMarshaledListener listener)419 static void addOnMarshaledListener(OnMarshaledListener listener) { 420 sOnMarshaledListener.get().add(listener); 421 } 422 423 /** 424 * Removes a listener for pending intents being written to a parcel. 425 * @hide 426 */ removeOnMarshaledListener(OnMarshaledListener listener)427 static void removeOnMarshaledListener(OnMarshaledListener listener) { 428 sOnMarshaledListener.get().remove(listener); 429 } 430 checkPendingIntent(int flags, @NonNull Intent intent, @NonNull Context context, boolean isActivityResultType)431 private static void checkPendingIntent(int flags, @NonNull Intent intent, 432 @NonNull Context context, boolean isActivityResultType) { 433 final boolean isFlagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0; 434 final boolean isFlagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; 435 final String packageName = context.getPackageName(); 436 437 if (isFlagImmutableSet && isFlagMutableSet) { 438 throw new IllegalArgumentException( 439 "Cannot set both FLAG_IMMUTABLE and FLAG_MUTABLE for PendingIntent"); 440 } 441 442 if (Compatibility.isChangeEnabled(PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED) 443 && !isFlagImmutableSet && !isFlagMutableSet) { 444 String msg = packageName + ": Targeting S+ (version " + Build.VERSION_CODES.S 445 + " and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE" 446 + " be specified when creating a PendingIntent.\nStrongly consider" 447 + " using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality" 448 + " depends on the PendingIntent being mutable, e.g. if it needs to" 449 + " be used with inline replies or bubbles."; 450 throw new IllegalArgumentException(msg); 451 } 452 453 // For apps with target SDK < U, warn that creation or retrieval of a mutable implicit 454 // PendingIntent that is not of type {@link ActivityManager#INTENT_SENDER_ACTIVITY_RESULT} 455 // will be blocked from target SDK U onwards for security reasons. The block itself 456 // happens on the server side, but this warning has to stay here to preserve the client 457 // side stack trace for app developers. 458 if (isNewMutableDisallowedImplicitPendingIntent(flags, intent, isActivityResultType) 459 && !Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) { 460 String msg = "New mutable implicit PendingIntent: pkg=" + packageName 461 + ", action=" + intent.getAction() 462 + ", featureId=" + context.getAttributionTag() 463 + ". This will be blocked once the app targets U+" 464 + " for security reasons."; 465 Log.w(TAG, new StackTrace(msg)); 466 } 467 } 468 469 /** @hide */ isNewMutableDisallowedImplicitPendingIntent(int flags, @NonNull Intent intent, boolean isActivityResultType)470 public static boolean isNewMutableDisallowedImplicitPendingIntent(int flags, 471 @NonNull Intent intent, boolean isActivityResultType) { 472 if (isActivityResultType) { 473 // Pending intents of type {@link ActivityManager#INTENT_SENDER_ACTIVITY_RESULT} 474 // should be ignored as they are intrinsically tied to a target which means they 475 // are already explicit. 476 return false; 477 } 478 boolean isFlagNoCreateSet = (flags & PendingIntent.FLAG_NO_CREATE) != 0; 479 boolean isFlagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0; 480 boolean isImplicit = (intent.getComponent() == null) && (intent.getPackage() == null); 481 boolean isFlagAllowUnsafeImplicitIntentSet = 482 (flags & PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT) != 0; 483 return !isFlagNoCreateSet && isFlagMutableSet && isImplicit 484 && !isFlagAllowUnsafeImplicitIntentSet; 485 } 486 487 /** 488 * Retrieve a PendingIntent that will start a new activity, like calling 489 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. 490 * Note that the activity will be started outside of the context of an 491 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 492 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. 493 * 494 * <p class="note">For security reasons, the {@link android.content.Intent} 495 * you supply here should almost always be an <em>explicit intent</em>, 496 * that is specify an explicit component to be delivered to through 497 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 498 * 499 * @param context The Context in which this PendingIntent should start 500 * the activity. 501 * @param requestCode Private request code for the sender 502 * @param intent Intent of the activity to be launched. 503 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 504 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 505 * or any of the flags as supported by 506 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 507 * of the intent that can be supplied when the actual send happens. 508 * 509 * @return Returns an existing or new PendingIntent matching the given 510 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 511 * supplied. 512 */ 513 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getActivity(Context context, int requestCode, Intent intent, @Flags int flags)514 public static PendingIntent getActivity(Context context, int requestCode, 515 Intent intent, @Flags int flags) { 516 return getActivity(context, requestCode, intent, flags, null); 517 } 518 519 /** 520 * Retrieve a PendingIntent that will start a new activity, like calling 521 * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. 522 * Note that the activity will be started outside of the context of an 523 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 524 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. 525 * 526 * <p class="note">For security reasons, the {@link android.content.Intent} 527 * you supply here should almost always be an <em>explicit intent</em>, 528 * that is specify an explicit component to be delivered to through 529 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 530 * 531 * @param context The Context in which this PendingIntent should start 532 * the activity. 533 * @param requestCode Private request code for the sender 534 * @param intent Intent of the activity to be launched. 535 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 536 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 537 * or any of the flags as supported by 538 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 539 * of the intent that can be supplied when the actual send happens. 540 * @param options Additional options for how the Activity should be started. 541 * May be null if there are no options. 542 * 543 * @return Returns an existing or new PendingIntent matching the given 544 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 545 * supplied. 546 */ 547 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getActivity(Context context, int requestCode, @NonNull Intent intent, @Flags int flags, @Nullable Bundle options)548 public static PendingIntent getActivity(Context context, int requestCode, 549 @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) { 550 // Some tests only mock Context.getUserId(), so fallback to the id Context.getUser() is null 551 final UserHandle user = context.getUser(); 552 return getActivityAsUser(context, requestCode, intent, flags, options, 553 user != null ? user : UserHandle.of(context.getUserId())); 554 } 555 556 /** 557 * @hide 558 * Note that UserHandle.CURRENT will be interpreted at the time the 559 * activity is started, not when the pending intent is created. 560 */ 561 @UnsupportedAppUsage getActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user)562 public static PendingIntent getActivityAsUser(Context context, int requestCode, 563 @NonNull Intent intent, int flags, Bundle options, UserHandle user) { 564 String packageName = context.getPackageName(); 565 String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver()); 566 checkPendingIntent(flags, intent, context, /* isActivityResultType */ false); 567 try { 568 intent.migrateExtraStreamToClipData(context); 569 intent.prepareToLeaveProcess(context); 570 IIntentSender target = 571 ActivityManager.getService().getIntentSenderWithFeature( 572 INTENT_SENDER_ACTIVITY, packageName, 573 context.getAttributionTag(), null, null, requestCode, new Intent[] { intent }, 574 resolvedType != null ? new String[] { resolvedType } : null, 575 flags, options, user.getIdentifier()); 576 return target != null ? new PendingIntent(target) : null; 577 } catch (RemoteException e) { 578 throw e.rethrowFromSystemServer(); 579 } 580 } 581 582 /** 583 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 584 * array of Intents to be supplied. The last Intent in the array is 585 * taken as the primary key for the PendingIntent, like the single Intent 586 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 587 * the resulting PendingIntent, all of the Intents are started in the same 588 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 589 * 590 * <p class="note"> 591 * The <em>first</em> intent in the array will be started outside of the context of an 592 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 593 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 594 * the first in the array are started in the context of the previous activity 595 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 596 * </p> 597 * 598 * <p class="note"> 599 * The <em>last</em> intent in the array represents the key for the 600 * PendingIntent. In other words, it is the significant element for matching 601 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 602 * its content will be the subject of replacement by 603 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 604 * This is because it is the most specific of the supplied intents, and the 605 * UI the user actually sees when the intents are started. 606 * </p> 607 * 608 * <p class="note">For security reasons, the {@link android.content.Intent} objects 609 * you supply here should almost always be <em>explicit intents</em>, 610 * that is specify an explicit component to be delivered to through 611 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 612 * 613 * @param context The Context in which this PendingIntent should start 614 * the activity. 615 * @param requestCode Private request code for the sender 616 * @param intents Array of Intents of the activities to be launched. 617 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 618 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 619 * or any of the flags as supported by 620 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 621 * of the intent that can be supplied when the actual send happens. 622 * 623 * @return Returns an existing or new PendingIntent matching the given 624 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 625 * supplied. 626 */ 627 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags)628 public static PendingIntent getActivities(Context context, int requestCode, 629 @NonNull Intent[] intents, @Flags int flags) { 630 return getActivities(context, requestCode, intents, flags, null); 631 } 632 633 /** 634 * Like {@link #getActivity(Context, int, Intent, int)}, but allows an 635 * array of Intents to be supplied. The last Intent in the array is 636 * taken as the primary key for the PendingIntent, like the single Intent 637 * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending 638 * the resulting PendingIntent, all of the Intents are started in the same 639 * way as they would be by passing them to {@link Context#startActivities(Intent[])}. 640 * 641 * <p class="note"> 642 * The <em>first</em> intent in the array will be started outside of the context of an 643 * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK 644 * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after 645 * the first in the array are started in the context of the previous activity 646 * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) 647 * </p> 648 * 649 * <p class="note"> 650 * The <em>last</em> intent in the array represents the key for the 651 * PendingIntent. In other words, it is the significant element for matching 652 * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, 653 * its content will be the subject of replacement by 654 * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. 655 * This is because it is the most specific of the supplied intents, and the 656 * UI the user actually sees when the intents are started. 657 * </p> 658 * 659 * <p class="note">For security reasons, the {@link android.content.Intent} objects 660 * you supply here should almost always be <em>explicit intents</em>, 661 * that is specify an explicit component to be delivered to through 662 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 663 * 664 * @param context The Context in which this PendingIntent should start 665 * the activity. 666 * @param requestCode Private request code for the sender 667 * @param intents Array of Intents of the activities to be launched. 668 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 669 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 670 * {@link #FLAG_IMMUTABLE} or any of the flags as supported by 671 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 672 * of the intent that can be supplied when the actual send happens. 673 * 674 * @return Returns an existing or new PendingIntent matching the given 675 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 676 * supplied. 677 */ 678 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options)679 public static PendingIntent getActivities(Context context, int requestCode, 680 @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) { 681 // Some tests only mock Context.getUserId(), so fallback to the id Context.getUser() is null 682 final UserHandle user = context.getUser(); 683 return getActivitiesAsUser(context, requestCode, intents, flags, options, 684 user != null ? user : UserHandle.of(context.getUserId())); 685 } 686 687 /** 688 * @hide 689 * Note that UserHandle.CURRENT will be interpreted at the time the 690 * activity is started, not when the pending intent is created. 691 */ getActivitiesAsUser(Context context, int requestCode, @NonNull Intent[] intents, int flags, Bundle options, UserHandle user)692 public static PendingIntent getActivitiesAsUser(Context context, int requestCode, 693 @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) { 694 String packageName = context.getPackageName(); 695 String[] resolvedTypes = new String[intents.length]; 696 for (int i=0; i<intents.length; i++) { 697 intents[i].migrateExtraStreamToClipData(context); 698 intents[i].prepareToLeaveProcess(context); 699 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver()); 700 checkPendingIntent(flags, intents[i], context, /* isActivityResultType */ false); 701 } 702 try { 703 IIntentSender target = 704 ActivityManager.getService().getIntentSenderWithFeature( 705 INTENT_SENDER_ACTIVITY, packageName, 706 context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes, 707 flags, options, user.getIdentifier()); 708 return target != null ? new PendingIntent(target) : null; 709 } catch (RemoteException e) { 710 throw e.rethrowFromSystemServer(); 711 } 712 } 713 714 /** 715 * Retrieve a PendingIntent that will perform a broadcast, like calling 716 * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}. 717 * 718 * <p class="note">For security reasons, the {@link android.content.Intent} 719 * you supply here should almost always be an <em>explicit intent</em>, 720 * that is specify an explicit component to be delivered to through 721 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 722 * 723 * @param context The Context in which this PendingIntent should perform 724 * the broadcast. 725 * @param requestCode Private request code for the sender 726 * @param intent The Intent to be broadcast. 727 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 728 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 729 * {@link #FLAG_IMMUTABLE} or any of the flags as supported by 730 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 731 * of the intent that can be supplied when the actual send happens. 732 * 733 * @return Returns an existing or new PendingIntent matching the given 734 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 735 * supplied. 736 */ 737 @SuppressWarnings("AndroidFrameworkPendingIntentMutability") getBroadcast(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)738 public static PendingIntent getBroadcast(Context context, int requestCode, 739 @NonNull Intent intent, @Flags int flags) { 740 return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser()); 741 } 742 743 /** 744 * @hide 745 * Note that UserHandle.CURRENT will be interpreted at the time the 746 * broadcast is sent, not when the pending intent is created. 747 */ 748 @UnsupportedAppUsage getBroadcastAsUser(Context context, int requestCode, Intent intent, int flags, UserHandle userHandle)749 public static PendingIntent getBroadcastAsUser(Context context, int requestCode, 750 Intent intent, int flags, UserHandle userHandle) { 751 String packageName = context.getPackageName(); 752 String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver()); 753 checkPendingIntent(flags, intent, context, /* isActivityResultType */ false); 754 try { 755 intent.prepareToLeaveProcess(context); 756 IIntentSender target = 757 ActivityManager.getService().getIntentSenderWithFeature( 758 INTENT_SENDER_BROADCAST, packageName, 759 context.getAttributionTag(), null, null, requestCode, new Intent[] { intent }, 760 resolvedType != null ? new String[] { resolvedType } : null, 761 flags, null, userHandle.getIdentifier()); 762 return target != null ? new PendingIntent(target) : null; 763 } catch (RemoteException e) { 764 throw e.rethrowFromSystemServer(); 765 } 766 } 767 768 /** 769 * Retrieve a PendingIntent that will start a service, like calling 770 * {@link Context#startService Context.startService()}. The start 771 * arguments given to the service will come from the extras of the Intent. 772 * 773 * <p class="note">For security reasons, the {@link android.content.Intent} 774 * you supply here should almost always be an <em>explicit intent</em>, 775 * that is specify an explicit component to be delivered to through 776 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 777 * 778 * @param context The Context in which this PendingIntent should start 779 * the service. 780 * @param requestCode Private request code for the sender 781 * @param intent An Intent describing the service to be started. 782 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 783 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 784 * {@link #FLAG_IMMUTABLE} or any of the flags as supported by 785 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 786 * of the intent that can be supplied when the actual send happens. 787 * 788 * @return Returns an existing or new PendingIntent matching the given 789 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 790 * supplied. 791 */ getService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)792 public static PendingIntent getService(Context context, int requestCode, 793 @NonNull Intent intent, @Flags int flags) { 794 return buildServicePendingIntent(context, requestCode, intent, flags, 795 INTENT_SENDER_SERVICE); 796 } 797 798 /** 799 * Retrieve a PendingIntent that will start a foreground service, like calling 800 * {@link Context#startForegroundService Context.startForegroundService()}. The start 801 * arguments given to the service will come from the extras of the Intent. 802 * 803 * <p class="note">For security reasons, the {@link android.content.Intent} 804 * you supply here should almost always be an <em>explicit intent</em>, 805 * that is specify an explicit component to be delivered to through 806 * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p> 807 * 808 * @param context The Context in which this PendingIntent should start 809 * the service. 810 * @param requestCode Private request code for the sender 811 * @param intent An Intent describing the service to be started. 812 * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, 813 * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, 814 * {@link #FLAG_IMMUTABLE} or any of the flags as supported by 815 * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts 816 * of the intent that can be supplied when the actual send happens. 817 * 818 * @return Returns an existing or new PendingIntent matching the given 819 * parameters. May return null only if {@link #FLAG_NO_CREATE} has been 820 * supplied. 821 */ getForegroundService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)822 public static PendingIntent getForegroundService(Context context, int requestCode, 823 @NonNull Intent intent, @Flags int flags) { 824 return buildServicePendingIntent(context, requestCode, intent, flags, 825 INTENT_SENDER_FOREGROUND_SERVICE); 826 } 827 buildServicePendingIntent(Context context, int requestCode, Intent intent, int flags, int serviceKind)828 private static PendingIntent buildServicePendingIntent(Context context, int requestCode, 829 Intent intent, int flags, int serviceKind) { 830 String packageName = context.getPackageName(); 831 String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver()); 832 checkPendingIntent(flags, intent, context, /* isActivityResultType */ false); 833 try { 834 intent.prepareToLeaveProcess(context); 835 IIntentSender target = 836 ActivityManager.getService().getIntentSenderWithFeature( 837 serviceKind, packageName, context.getAttributionTag(), 838 null, null, requestCode, new Intent[] { intent }, 839 resolvedType != null ? new String[] { resolvedType } : null, 840 flags, null, context.getUserId()); 841 return target != null ? new PendingIntent(target) : null; 842 } catch (RemoteException e) { 843 throw e.rethrowFromSystemServer(); 844 } 845 } 846 847 /** 848 * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent 849 * 850 * @return Returns a IntentSender object that wraps the sender of PendingIntent 851 * 852 */ 853 @NonNull getIntentSender()854 public IntentSender getIntentSender() { 855 return new IntentSender(mTarget, mWhitelistToken); 856 } 857 858 /** 859 * Cancel a currently active PendingIntent. Only the original application 860 * owning a PendingIntent can cancel it. 861 */ cancel()862 public void cancel() { 863 try { 864 ActivityManager.getService().cancelIntentSender(mTarget); 865 } catch (RemoteException e) { 866 throw e.rethrowFromSystemServer(); 867 } 868 } 869 870 /** 871 * Perform the operation associated with this PendingIntent. 872 * 873 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 874 * Bundle) 875 * 876 * @throws CanceledException Throws CanceledException if the PendingIntent 877 * is no longer allowing more intents to be sent through it. 878 */ send()879 public void send() throws CanceledException { 880 send(null, 0, null, null, null, null, null); 881 } 882 883 /** 884 * Perform the operation associated with this PendingIntent. 885 * 886 * @param code Result code to supply back to the PendingIntent's target. 887 * 888 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 889 * Bundle) 890 * 891 * @throws CanceledException Throws CanceledException if the PendingIntent 892 * is no longer allowing more intents to be sent through it. 893 */ send(int code)894 public void send(int code) throws CanceledException { 895 send(null, code, null, null, null, null, null); 896 } 897 898 /** 899 * Perform the operation associated with this PendingIntent, allowing the 900 * caller to specify information about the Intent to use. 901 * 902 * @param context The Context of the caller. 903 * @param code Result code to supply back to the PendingIntent's target. 904 * @param intent Additional Intent data. See {@link Intent#fillIn 905 * Intent.fillIn()} for information on how this is applied to the 906 * original Intent. If flag {@link #FLAG_IMMUTABLE} was set when this 907 * pending intent was created, this argument will be ignored. 908 * 909 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 910 * Bundle) 911 * 912 * @throws CanceledException Throws CanceledException if the PendingIntent 913 * is no longer allowing more intents to be sent through it. 914 */ send(Context context, int code, @Nullable Intent intent)915 public void send(Context context, int code, @Nullable Intent intent) 916 throws CanceledException { 917 send(context, code, intent, null, null, null, null); 918 } 919 920 /** 921 * Perform the operation associated with this PendingIntent, supplying additional 922 * options for the operation. 923 * 924 * @param options Additional options the caller would like to provide to modify the 925 * sending behavior. May be built from an {@link ActivityOptions} to apply to an 926 * activity start. 927 * 928 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String) 929 * 930 * @throws CanceledException Throws CanceledException if the PendingIntent 931 * is no longer allowing more intents to be sent through it. 932 */ send(@ullable Bundle options)933 public void send(@Nullable Bundle options) throws CanceledException { 934 send(null, 0, null, null, null, null, options); 935 } 936 937 /** 938 * Perform the operation associated with this PendingIntent, allowing the 939 * caller to be notified when the send has completed. 940 * 941 * @param code Result code to supply back to the PendingIntent's target. 942 * @param onFinished The object to call back on when the send has 943 * completed, or null for no callback. 944 * @param handler Handler identifying the thread on which the callback 945 * should happen. If null, the callback will happen from the thread 946 * pool of the process. 947 * 948 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 949 * Bundle) 950 * 951 * @throws CanceledException Throws CanceledException if the PendingIntent 952 * is no longer allowing more intents to be sent through it. 953 */ send(int code, @Nullable OnFinished onFinished, @Nullable Handler handler)954 public void send(int code, @Nullable OnFinished onFinished, @Nullable Handler handler) 955 throws CanceledException { 956 send(null, code, null, onFinished, handler, null, null); 957 } 958 959 /** 960 * Perform the operation associated with this PendingIntent, allowing the 961 * caller to specify information about the Intent to use and be notified 962 * when the send has completed. 963 * 964 * <p>For the intent parameter, a PendingIntent 965 * often has restrictions on which fields can be supplied here, based on 966 * how the PendingIntent was retrieved in {@link #getActivity}, 967 * {@link #getBroadcast}, or {@link #getService}. 968 * 969 * @param context The Context of the caller. This may be null if 970 * <var>intent</var> is also null. 971 * @param code Result code to supply back to the PendingIntent's target. 972 * @param intent Additional Intent data. See {@link Intent#fillIn 973 * Intent.fillIn()} for information on how this is applied to the 974 * original Intent. Use null to not modify the original Intent. 975 * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was 976 * created, this argument will be ignored. 977 * @param onFinished The object to call back on when the send has 978 * completed, or null for no callback. 979 * @param handler Handler identifying the thread on which the callback 980 * should happen. If null, the callback will happen from the thread 981 * pool of the process. 982 * 983 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 984 * Bundle) 985 * 986 * @throws CanceledException Throws CanceledException if the PendingIntent 987 * is no longer allowing more intents to be sent through it. 988 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler)989 public void send(Context context, int code, @Nullable Intent intent, 990 @Nullable OnFinished onFinished, @Nullable Handler handler) throws CanceledException { 991 send(context, code, intent, onFinished, handler, null, null); 992 } 993 994 /** 995 * Perform the operation associated with this PendingIntent, allowing the 996 * caller to specify information about the Intent to use and be notified 997 * when the send has completed. 998 * 999 * <p>For the intent parameter, a PendingIntent 1000 * often has restrictions on which fields can be supplied here, based on 1001 * how the PendingIntent was retrieved in {@link #getActivity}, 1002 * {@link #getBroadcast}, or {@link #getService}. 1003 * 1004 * @param context The Context of the caller. This may be null if 1005 * <var>intent</var> is also null. 1006 * @param code Result code to supply back to the PendingIntent's target. 1007 * @param intent Additional Intent data. See {@link Intent#fillIn 1008 * Intent.fillIn()} for information on how this is applied to the 1009 * original Intent. Use null to not modify the original Intent. 1010 * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was 1011 * created, this argument will be ignored. 1012 * @param onFinished The object to call back on when the send has 1013 * completed, or null for no callback. 1014 * @param handler Handler identifying the thread on which the callback 1015 * should happen. If null, the callback will happen from the thread 1016 * pool of the process. 1017 * @param requiredPermission Name of permission that a recipient of the PendingIntent 1018 * is required to hold. This is only valid for broadcast intents, and 1019 * corresponds to the permission argument in 1020 * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. 1021 * If null, no permission is required. 1022 * 1023 * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler, String, 1024 * Bundle) 1025 * 1026 * @throws CanceledException Throws CanceledException if the PendingIntent 1027 * is no longer allowing more intents to be sent through it. 1028 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission)1029 public void send(Context context, int code, @Nullable Intent intent, 1030 @Nullable OnFinished onFinished, @Nullable Handler handler, 1031 @Nullable String requiredPermission) 1032 throws CanceledException { 1033 send(context, code, intent, onFinished, handler, requiredPermission, null); 1034 } 1035 1036 /** 1037 * Perform the operation associated with this PendingIntent, allowing the 1038 * caller to specify information about the Intent to use and be notified 1039 * when the send has completed. 1040 * 1041 * <p>For the intent parameter, a PendingIntent 1042 * often has restrictions on which fields can be supplied here, based on 1043 * how the PendingIntent was retrieved in {@link #getActivity}, 1044 * {@link #getBroadcast}, or {@link #getService}. 1045 * 1046 * @param context The Context of the caller. This may be null if 1047 * <var>intent</var> is also null. 1048 * @param code Result code to supply back to the PendingIntent's target. 1049 * @param intent Additional Intent data. See {@link Intent#fillIn 1050 * Intent.fillIn()} for information on how this is applied to the 1051 * original Intent. Use null to not modify the original Intent. 1052 * If flag {@link #FLAG_IMMUTABLE} was set when this pending intent was 1053 * created, this argument will be ignored. 1054 * @param onFinished The object to call back on when the send has 1055 * completed, or null for no callback. 1056 * @param handler Handler identifying the thread on which the callback 1057 * should happen. If null, the callback will happen from the thread 1058 * pool of the process. 1059 * @param requiredPermission Name of permission that a recipient of the PendingIntent 1060 * is required to hold. This is only valid for broadcast intents, and 1061 * corresponds to the permission argument in 1062 * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}. 1063 * If null, no permission is required. 1064 * @param options Additional options the caller would like to provide to modify the sending 1065 * behavior. May be built from an {@link ActivityOptions} to apply to an activity start. 1066 * 1067 * @throws CanceledException Throws CanceledException if the PendingIntent 1068 * is no longer allowing more intents to be sent through it. 1069 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission, @Nullable Bundle options)1070 public void send(Context context, int code, @Nullable Intent intent, 1071 @Nullable OnFinished onFinished, @Nullable Handler handler, 1072 @Nullable String requiredPermission, @Nullable Bundle options) 1073 throws CanceledException { 1074 if (sendAndReturnResult(context, code, intent, onFinished, handler, requiredPermission, 1075 options) < 0) { 1076 throw new CanceledException(); 1077 } 1078 } 1079 1080 /** 1081 * Like {@link #send}, but returns the result 1082 * @hide 1083 */ sendAndReturnResult(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission, @Nullable Bundle options)1084 public int sendAndReturnResult(Context context, int code, @Nullable Intent intent, 1085 @Nullable OnFinished onFinished, @Nullable Handler handler, 1086 @Nullable String requiredPermission, @Nullable Bundle options) 1087 throws CanceledException { 1088 try { 1089 String resolvedType = intent != null ? 1090 intent.resolveTypeIfNeeded(context.getContentResolver()) 1091 : null; 1092 1093 if (context != null && isActivity()) { 1094 // Set the context display id as preferred for this activity launches, so that it 1095 // can land on caller's display. Or just brought the task to front at the display 1096 // where it was on since it has higher preference. 1097 ActivityOptions activityOptions = options != null ? new ActivityOptions(options) 1098 : ActivityOptions.makeBasic(); 1099 activityOptions.setCallerDisplayId(context.getDisplayId()); 1100 options = activityOptions.toBundle(); 1101 } 1102 1103 final IApplicationThread app = ActivityThread.currentActivityThread() 1104 .getApplicationThread(); 1105 return ActivityManager.getService().sendIntentSender(app, 1106 mTarget, mWhitelistToken, code, intent, resolvedType, 1107 onFinished != null 1108 ? new FinishedDispatcher(this, onFinished, handler) 1109 : null, 1110 requiredPermission, options); 1111 } catch (RemoteException e) { 1112 throw new CanceledException(e); 1113 } 1114 } 1115 1116 /** 1117 * @deprecated Renamed to {@link #getCreatorPackage()}. 1118 */ 1119 @Deprecated 1120 @Nullable getTargetPackage()1121 public String getTargetPackage() { 1122 return getCreatorPackage(); 1123 } 1124 1125 /** 1126 * Return the package name of the application that created this 1127 * PendingIntent, that is the identity under which you will actually be 1128 * sending the Intent. The returned string is supplied by the system, so 1129 * that an application can not spoof its package. 1130 * 1131 * <p class="note">Be careful about how you use this. All this tells you is 1132 * who created the PendingIntent. It does <strong>not</strong> tell you who 1133 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 1134 * passed between applications, so the PendingIntent you receive from an application 1135 * could actually be one it received from another application, meaning the result 1136 * you get here will identify the original application. Because of this, you should 1137 * only use this information to identify who you expect to be interacting with 1138 * through a {@link #send} call, not who gave you the PendingIntent.</p> 1139 * 1140 * @return The package name of the PendingIntent. 1141 */ 1142 @Nullable getCreatorPackage()1143 public String getCreatorPackage() { 1144 return getCachedInfo().getCreatorPackage(); 1145 } 1146 1147 /** 1148 * Return the uid of the application that created this 1149 * PendingIntent, that is the identity under which you will actually be 1150 * sending the Intent. The returned integer is supplied by the system, so 1151 * that an application can not spoof its uid. 1152 * 1153 * <p class="note">Be careful about how you use this. All this tells you is 1154 * who created the PendingIntent. It does <strong>not</strong> tell you who 1155 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 1156 * passed between applications, so the PendingIntent you receive from an application 1157 * could actually be one it received from another application, meaning the result 1158 * you get here will identify the original application. Because of this, you should 1159 * only use this information to identify who you expect to be interacting with 1160 * through a {@link #send} call, not who gave you the PendingIntent.</p> 1161 * 1162 * @return The uid of the PendingIntent, or -1 if there is 1163 * none associated with it. 1164 */ getCreatorUid()1165 public int getCreatorUid() { 1166 return getCachedInfo().getCreatorUid(); 1167 } 1168 1169 /** 1170 * @hide 1171 * @deprecated use {@link #addCancelListener(Executor, CancelListener)} instead. 1172 */ 1173 @Deprecated registerCancelListener(@onNull CancelListener cancelListener)1174 public void registerCancelListener(@NonNull CancelListener cancelListener) { 1175 if (!addCancelListener(Runnable::run, cancelListener)) { 1176 // Call the callback right away synchronously, if the PI has been canceled already. 1177 cancelListener.onCanceled(this); 1178 } 1179 } 1180 1181 /** 1182 * Register a listener to when this pendingIntent is canceled. 1183 * 1184 * @return true if the listener has been set successfully. false if the {@link PendingIntent} 1185 * has already been canceled. 1186 * 1187 * @hide 1188 */ 1189 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 1190 @TestApi addCancelListener(@onNull Executor executor, @NonNull CancelListener cancelListener)1191 public boolean addCancelListener(@NonNull Executor executor, 1192 @NonNull CancelListener cancelListener) { 1193 synchronized (mTarget) { 1194 if (mCancelListerInfo != null && mCancelListerInfo.mCanceled) { 1195 return false; 1196 } 1197 if (mCancelListerInfo == null) { 1198 mCancelListerInfo = new CancelListerInfo(); 1199 } 1200 final CancelListerInfo cli = mCancelListerInfo; 1201 1202 boolean wasEmpty = cli.mCancelListeners.isEmpty(); 1203 cli.mCancelListeners.add(Pair.create(executor, cancelListener)); 1204 if (wasEmpty) { 1205 boolean success; 1206 try { 1207 success = ActivityManager.getService().registerIntentSenderCancelListenerEx( 1208 mTarget, cli); 1209 } catch (RemoteException e) { 1210 throw e.rethrowFromSystemServer(); 1211 } 1212 if (!success) { 1213 cli.mCanceled = true; 1214 } 1215 return success; 1216 } else { 1217 return !cli.mCanceled; 1218 } 1219 } 1220 } 1221 notifyCancelListeners()1222 private void notifyCancelListeners() { 1223 ArraySet<Pair<Executor, CancelListener>> cancelListeners; 1224 synchronized (mTarget) { 1225 // When notifyCancelListeners() is called, mCancelListerInfo must always be non-null. 1226 final CancelListerInfo cli = mCancelListerInfo; 1227 cli.mCanceled = true; 1228 cancelListeners = new ArraySet<>(cli.mCancelListeners); 1229 cli.mCancelListeners.clear(); 1230 } 1231 int size = cancelListeners.size(); 1232 for (int i = 0; i < size; i++) { 1233 final Pair<Executor, CancelListener> pair = cancelListeners.valueAt(i); 1234 pair.first.execute(() -> pair.second.onCanceled(this)); 1235 } 1236 } 1237 1238 /** 1239 * @hide 1240 * @deprecated use {@link #removeCancelListener(CancelListener)} instead. 1241 */ 1242 @Deprecated unregisterCancelListener(CancelListener cancelListener)1243 public void unregisterCancelListener(CancelListener cancelListener) { 1244 removeCancelListener(cancelListener); 1245 } 1246 1247 /** 1248 * Un-register a listener to when this pendingIntent is canceled. 1249 * 1250 * @hide 1251 */ 1252 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 1253 @TestApi removeCancelListener(@onNull CancelListener cancelListener)1254 public void removeCancelListener(@NonNull CancelListener cancelListener) { 1255 synchronized (mTarget) { 1256 final CancelListerInfo cli = mCancelListerInfo; 1257 if (cli == null || cli.mCancelListeners.size() == 0) { 1258 return; 1259 } 1260 for (int i = cli.mCancelListeners.size() - 1; i >= 0; i--) { 1261 if (cli.mCancelListeners.valueAt(i).second == cancelListener) { 1262 cli.mCancelListeners.removeAt(i); 1263 } 1264 } 1265 if (cli.mCancelListeners.isEmpty()) { 1266 try { 1267 ActivityManager.getService().unregisterIntentSenderCancelListener(mTarget, 1268 cli); 1269 } catch (RemoteException e) { 1270 throw e.rethrowFromSystemServer(); 1271 } 1272 } 1273 } 1274 } 1275 1276 /** 1277 * Return the user handle of the application that created this 1278 * PendingIntent, that is the user under which you will actually be 1279 * sending the Intent. The returned UserHandle is supplied by the system, so 1280 * that an application can not spoof its user. See 1281 * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for 1282 * more explanation of user handles. 1283 * 1284 * <p class="note">Be careful about how you use this. All this tells you is 1285 * who created the PendingIntent. It does <strong>not</strong> tell you who 1286 * handed the PendingIntent to you: that is, PendingIntent objects are intended to be 1287 * passed between applications, so the PendingIntent you receive from an application 1288 * could actually be one it received from another application, meaning the result 1289 * you get here will identify the original application. Because of this, you should 1290 * only use this information to identify who you expect to be interacting with 1291 * through a {@link #send} call, not who gave you the PendingIntent.</p> 1292 * 1293 * @return The user handle of the PendingIntent 1294 */ 1295 @NonNull getCreatorUserHandle()1296 public UserHandle getCreatorUserHandle() { 1297 int uid = getCachedInfo().getCreatorUid(); 1298 return UserHandle.getUserHandleForUid(uid); 1299 } 1300 1301 /** 1302 * @hide 1303 * Check to verify that this PendingIntent targets a specific package. 1304 */ isTargetedToPackage()1305 public boolean isTargetedToPackage() { 1306 try { 1307 return ActivityManager.getService() 1308 .isIntentSenderTargetedToPackage(mTarget); 1309 } catch (RemoteException e) { 1310 throw e.rethrowFromSystemServer(); 1311 } 1312 } 1313 1314 /** 1315 * Check if this PendingIntent is marked with {@link #FLAG_IMMUTABLE}. 1316 */ isImmutable()1317 public boolean isImmutable() { 1318 return getCachedInfo().isImmutable(); 1319 } 1320 1321 /** 1322 * @return TRUE if this {@link PendingIntent} was created with 1323 * {@link #getActivity} or {@link #getActivities}. 1324 */ isActivity()1325 public boolean isActivity() { 1326 return getCachedInfo().getIntentSenderType() == INTENT_SENDER_ACTIVITY; 1327 } 1328 1329 /** 1330 * @return TRUE if this {@link PendingIntent} was created with {@link #getForegroundService}. 1331 */ isForegroundService()1332 public boolean isForegroundService() { 1333 return getCachedInfo().getIntentSenderType() == INTENT_SENDER_FOREGROUND_SERVICE; 1334 } 1335 1336 /** 1337 * @return TRUE if this {@link PendingIntent} was created with {@link #getService}. 1338 */ isService()1339 public boolean isService() { 1340 return getCachedInfo().getIntentSenderType() == INTENT_SENDER_SERVICE; 1341 } 1342 1343 /** 1344 * @return TRUE if this {@link PendingIntent} was created with {@link #getBroadcast}. 1345 */ isBroadcast()1346 public boolean isBroadcast() { 1347 return getCachedInfo().getIntentSenderType() == INTENT_SENDER_BROADCAST; 1348 } 1349 1350 /** 1351 * @hide 1352 * Return the Intent of this PendingIntent. 1353 */ 1354 @UnsupportedAppUsage getIntent()1355 public Intent getIntent() { 1356 try { 1357 return ActivityManager.getService() 1358 .getIntentForIntentSender(mTarget); 1359 } catch (RemoteException e) { 1360 throw e.rethrowFromSystemServer(); 1361 } 1362 } 1363 1364 /** 1365 * @hide 1366 * Return descriptive tag for this PendingIntent. 1367 */ 1368 @UnsupportedAppUsage getTag(String prefix)1369 public String getTag(String prefix) { 1370 try { 1371 return ActivityManager.getService() 1372 .getTagForIntentSender(mTarget, prefix); 1373 } catch (RemoteException e) { 1374 throw e.rethrowFromSystemServer(); 1375 } 1376 } 1377 1378 /** 1379 * Resolve the intent set in this {@link PendingIntent}. Note if the pending intent is 1380 * generated for another user, the resulting component may not exist on the calling user. 1381 * Use {@link android.content.pm.ApplicationInfo#uid} of the resulting 1382 * {@link android.content.pm.ComponentInfo} with 1383 * {@link android.os.UserHandle#getUserHandleForUid(int)} to see which user will receive 1384 * the intent. 1385 * 1386 * @param flags MATCH_* flags from {@link android.content.pm.PackageManager}. 1387 * @hide 1388 */ 1389 @RequiresPermission(permission.GET_INTENT_SENDER_INTENT) 1390 @SystemApi(client = Client.MODULE_LIBRARIES) 1391 @TestApi queryIntentComponents(@esolveInfoFlagsBits int flags)1392 public @NonNull List<ResolveInfo> queryIntentComponents(@ResolveInfoFlagsBits int flags) { 1393 try { 1394 ParceledListSlice<ResolveInfo> parceledList = ActivityManager.getService() 1395 .queryIntentComponentsForIntentSender(mTarget, flags); 1396 if (parceledList == null) { 1397 return Collections.emptyList(); 1398 } 1399 return parceledList.getList(); 1400 } catch (RemoteException e) { 1401 throw e.rethrowFromSystemServer(); 1402 } 1403 } 1404 1405 /** 1406 * Comparison operator on two PendingIntent objects, such that true is returned when they 1407 * represent {@link Intent}s that are equal as per {@link Intent#filterEquals}. 1408 * 1409 * @param other The other PendingIntent to compare against. 1410 * @return True if action, data, type, class, and categories on two intents are the same. 1411 * 1412 * @hide 1413 */ 1414 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 1415 @TestApi 1416 @RequiresPermission(android.Manifest.permission.GET_INTENT_SENDER_INTENT) intentFilterEquals(@ullable PendingIntent other)1417 public boolean intentFilterEquals(@Nullable PendingIntent other) { 1418 if (other == null) { 1419 return false; 1420 } 1421 try { 1422 return ActivityManager.getService().getIntentForIntentSender(other.mTarget) 1423 .filterEquals(getIntent()); 1424 } catch (RemoteException e) { 1425 throw e.rethrowFromSystemServer(); 1426 } 1427 } 1428 1429 /** 1430 * Comparison operator on two PendingIntent objects, such that true 1431 * is returned then they both represent the same operation from the 1432 * same package. This allows you to use {@link #getActivity}, 1433 * {@link #getBroadcast}, or {@link #getService} multiple times (even 1434 * across a process being killed), resulting in different PendingIntent 1435 * objects but whose equals() method identifies them as being the same 1436 * operation. 1437 */ 1438 @Override equals(@ullable Object otherObj)1439 public boolean equals(@Nullable Object otherObj) { 1440 if (otherObj instanceof PendingIntent) { 1441 return mTarget.asBinder().equals(((PendingIntent)otherObj) 1442 .mTarget.asBinder()); 1443 } 1444 return false; 1445 } 1446 1447 @Override hashCode()1448 public int hashCode() { 1449 return mTarget.asBinder().hashCode(); 1450 } 1451 1452 @Override toString()1453 public String toString() { 1454 StringBuilder sb = new StringBuilder(128); 1455 sb.append("PendingIntent{"); 1456 sb.append(Integer.toHexString(System.identityHashCode(this))); 1457 sb.append(": "); 1458 sb.append(mTarget.asBinder()); 1459 sb.append('}'); 1460 return sb.toString(); 1461 } 1462 1463 /** @hide */ dumpDebug(ProtoOutputStream proto, long fieldId)1464 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 1465 final long token = proto.start(fieldId); 1466 proto.write(PendingIntentProto.TARGET, mTarget.asBinder().toString()); 1467 proto.end(token); 1468 } 1469 describeContents()1470 public int describeContents() { 1471 return 0; 1472 } 1473 writeToParcel(Parcel out, int flags)1474 public void writeToParcel(Parcel out, int flags) { 1475 out.writeStrongBinder(mTarget.asBinder()); 1476 final List<OnMarshaledListener> listeners = sOnMarshaledListener.get(); 1477 final int numListeners = listeners.size(); 1478 for (int i = 0; i < numListeners; i++) { 1479 listeners.get(i).onMarshaled(this, out, flags); 1480 } 1481 } 1482 1483 public static final @NonNull Creator<PendingIntent> CREATOR = new Creator<PendingIntent>() { 1484 public PendingIntent createFromParcel(Parcel in) { 1485 IBinder target = in.readStrongBinder(); 1486 return target != null 1487 ? new PendingIntent(target, in.getClassCookie(PendingIntent.class)) 1488 : null; 1489 } 1490 1491 public PendingIntent[] newArray(int size) { 1492 return new PendingIntent[size]; 1493 } 1494 }; 1495 1496 /** 1497 * Convenience function for writing either a PendingIntent or null pointer to 1498 * a Parcel. You must use this with {@link #readPendingIntentOrNullFromParcel} 1499 * for later reading it. 1500 * 1501 * @param sender The PendingIntent to write, or null. 1502 * @param out Where to write the PendingIntent. 1503 */ writePendingIntentOrNullToParcel(@ullable PendingIntent sender, @NonNull Parcel out)1504 public static void writePendingIntentOrNullToParcel(@Nullable PendingIntent sender, 1505 @NonNull Parcel out) { 1506 out.writeStrongBinder(sender != null ? sender.mTarget.asBinder() : null); 1507 if (sender != null) { 1508 final List<OnMarshaledListener> listeners = sOnMarshaledListener.get(); 1509 final int numListeners = listeners.size(); 1510 for (int i = 0; i < numListeners; i++) { 1511 listeners.get(i).onMarshaled(sender, out, 0 /* flags */); 1512 } 1513 } 1514 } 1515 1516 /** 1517 * Convenience function for reading either a PendingIntent or null pointer from 1518 * a Parcel. You must have previously written the PendingIntent with 1519 * {@link #writePendingIntentOrNullToParcel}. 1520 * 1521 * @param in The Parcel containing the written PendingIntent. 1522 * 1523 * @return Returns the PendingIntent read from the Parcel, or null if null had 1524 * been written. 1525 */ 1526 @Nullable readPendingIntentOrNullFromParcel(@onNull Parcel in)1527 public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) { 1528 IBinder b = in.readStrongBinder(); 1529 return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null; 1530 } 1531 1532 /** 1533 * Creates a PendingIntent with the given target. 1534 * @param target the backing IIntentSender 1535 * @hide 1536 */ PendingIntent(IIntentSender target)1537 public PendingIntent(IIntentSender target) { 1538 mTarget = Objects.requireNonNull(target); 1539 } 1540 PendingIntent(IBinder target, Object cookie)1541 /*package*/ PendingIntent(IBinder target, Object cookie) { 1542 mTarget = Objects.requireNonNull(IIntentSender.Stub.asInterface(target)); 1543 if (cookie != null) { 1544 mWhitelistToken = (IBinder)cookie; 1545 } 1546 } 1547 1548 /** @hide */ getTarget()1549 public IIntentSender getTarget() { 1550 return mTarget; 1551 } 1552 1553 /** @hide */ getWhitelistToken()1554 public IBinder getWhitelistToken() { 1555 return mWhitelistToken; 1556 } 1557 1558 /** 1559 * A listener to when a pending intent is canceled 1560 * 1561 * @hide 1562 */ 1563 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 1564 @TestApi 1565 public interface CancelListener { 1566 /** 1567 * Called when a Pending Intent is canceled. 1568 * 1569 * @param intent The intent that was canceled. 1570 */ onCanceled(@onNull PendingIntent intent)1571 void onCanceled(@NonNull PendingIntent intent); 1572 } 1573 getCachedInfo()1574 private PendingIntentInfo getCachedInfo() { 1575 if (mCachedInfo == null) { 1576 try { 1577 mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget); 1578 } catch (RemoteException e) { 1579 throw e.rethrowFromSystemServer(); 1580 } 1581 } 1582 1583 return mCachedInfo; 1584 } 1585 } 1586