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