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