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