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