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 17package android.app; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.annotation.Nullable; 22import android.content.Context; 23import android.content.IIntentReceiver; 24import android.content.IIntentSender; 25import android.content.Intent; 26import android.content.IntentSender; 27import android.os.Bundle; 28import android.os.Handler; 29import android.os.IBinder; 30import android.os.Looper; 31import android.os.Parcel; 32import android.os.Parcelable; 33import android.os.RemoteException; 34import android.os.UserHandle; 35import android.util.AndroidException; 36import android.util.ArraySet; 37import android.util.proto.ProtoOutputStream; 38 39import com.android.internal.os.IResultReceiver; 40 41import java.lang.annotation.Retention; 42import 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 */ 97public 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 { 175 public CanceledException() { 176 } 177 178 public CanceledException(String name) { 179 super(name); 180 } 181 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 */ 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; 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 } 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 } 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 1154 public int hashCode() { 1155 return mTarget.asBinder().hashCode(); 1156 } 1157 1158 @Override 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 */ 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 1178 public int describeContents() { 1179 return 0; 1180 } 1181 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 */ 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 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 1240 /*package*/ PendingIntent(IIntentSender target) { 1241 mTarget = target; 1242 } 1243 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 */ 1252 public IIntentSender getTarget() { 1253 return mTarget; 1254 } 1255 1256 /** @hide */ 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 */ 1272 void onCancelled(PendingIntent intent); 1273 } 1274} 1275