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 { CanceledException()176 public CanceledException() { 177 } 178 CanceledException(String name)179 public CanceledException(String name) { 180 super(name); 181 } 182 CanceledException(Exception cause)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 */ onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)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; FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler)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 } performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean serialized, boolean sticky, int sendingUser)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 } run()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 */ onMarshaled(PendingIntent intent, Parcel parcel, int flags)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 setOnMarshaledListener(OnMarshaledListener listener)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 */ getActivity(Context context, int requestCode, Intent intent, @Flags int flags)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 */ getActivity(Context context, int requestCode, @NonNull Intent intent, @Flags int flags, @Nullable Bundle options)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 getActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user)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 */ getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags)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 */ getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options)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 */ getActivitiesAsUser(Context context, int requestCode, @NonNull Intent[] intents, int flags, Bundle options, UserHandle user)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 */ getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags)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 getBroadcastAsUser(Context context, int requestCode, Intent intent, int flags, UserHandle userHandle)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 */ getService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)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 */ getForegroundService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)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 buildServicePendingIntent(Context context, int requestCode, Intent intent, int flags, int serviceKind)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 */ getIntentSender()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 */ cancel()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 */ send()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 */ send(int code)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 */ send(Context context, int code, @Nullable Intent intent)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 */ send(int code, @Nullable OnFinished onFinished, @Nullable Handler handler)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 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler)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 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission)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 */ send(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission, @Nullable Bundle options)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 */ sendAndReturnResult(Context context, int code, @Nullable Intent intent, @Nullable OnFinished onFinished, @Nullable Handler handler, @Nullable String requiredPermission, @Nullable Bundle options)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 getTargetPackage()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 getCreatorPackage()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 */ getCreatorUid()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 */ registerCancelListener(CancelListener cancelListener)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 notifyCancelListeners()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 */ unregisterCancelListener(CancelListener cancelListener)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 getCreatorUserHandle()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 */ isTargetedToPackage()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 isActivity()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 */ isForegroundService()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 */ isBroadcast()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 getIntent()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 getTag(String prefix)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 equals(Object otherObj)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 hashCode()1174 public int hashCode() { 1175 return mTarget.asBinder().hashCode(); 1176 } 1177 1178 @Override toString()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 */ writeToProto(ProtoOutputStream proto, long fieldId)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 describeContents()1198 public int describeContents() { 1199 return 0; 1200 } 1201 writeToParcel(Parcel out, int flags)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 */ writePendingIntentOrNullToParcel(@ullable PendingIntent sender, @NonNull Parcel out)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 readPendingIntentOrNullFromParcel(@onNull Parcel in)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 PendingIntent(IIntentSender target)1260 /*package*/ PendingIntent(IIntentSender target) { 1261 mTarget = target; 1262 } 1263 PendingIntent(IBinder target, Object cookie)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 */ getTarget()1272 public IIntentSender getTarget() { 1273 return mTarget; 1274 } 1275 1276 /** @hide */ getWhitelistToken()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 */ onCancelled(PendingIntent intent)1292 void onCancelled(PendingIntent intent); 1293 } 1294 } 1295