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