• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Intent;
24 import android.content.IIntentReceiver;
25 import android.content.IIntentSender;
26 import android.content.IntentSender;
27 import android.os.Bundle;
28 import android.os.RemoteException;
29 import android.os.Handler;
30 import android.os.IBinder;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 import android.os.UserHandle;
34 import android.util.AndroidException;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 
39 /**
40  * A description of an Intent and target action to perform with it.  Instances
41  * of this class are created with {@link #getActivity}, {@link #getActivities},
42  * {@link #getBroadcast}, and {@link #getService}; the returned object can be
43  * handed to other applications so that they can perform the action you
44  * described on your behalf at a later time.
45  *
46  * <p>By giving a PendingIntent to another application,
47  * you are granting it the right to perform the operation you have specified
48  * as if the other application was yourself (with the same permissions and
49  * identity).  As such, you should be careful about how you build the PendingIntent:
50  * almost always, for example, the base Intent you supply should have the component
51  * name explicitly set to one of your own components, to ensure it is ultimately
52  * sent there and nowhere else.
53  *
54  * <p>A PendingIntent itself is simply a reference to a token maintained by
55  * the system describing the original data used to retrieve it.  This means
56  * that, even if its owning application's process is killed, the
57  * PendingIntent itself will remain usable from other processes that
58  * have been given it.  If the creating application later re-retrieves the
59  * same kind of PendingIntent (same operation, same Intent action, data,
60  * categories, and components, and same flags), it will receive a PendingIntent
61  * representing the same token if that is still valid, and can thus call
62  * {@link #cancel} to remove it.
63  *
64  * <p>Because of this behavior, it is important to know when two Intents
65  * are considered to be the same for purposes of retrieving a PendingIntent.
66  * A common mistake people make is to create multiple PendingIntent objects
67  * with Intents that only vary in their "extra" contents, expecting to get
68  * a different PendingIntent each time.  This does <em>not</em> happen.  The
69  * parts of the Intent that are used for matching are the same ones defined
70  * by {@link Intent#filterEquals(Intent) Intent.filterEquals}.  If you use two
71  * Intent objects that are equivalent as per
72  * {@link Intent#filterEquals(Intent) Intent.filterEquals}, then you will get
73  * the same PendingIntent for both of them.
74  *
75  * <p>There are two typical ways to deal with this.
76  *
77  * <p>If you truly need multiple distinct PendingIntent objects active at
78  * the same time (such as to use as two notifications that are both shown
79  * at the same time), then you will need to ensure there is something that
80  * is different about them to associate them with different PendingIntents.
81  * This may be any of the Intent attributes considered by
82  * {@link Intent#filterEquals(Intent) Intent.filterEquals}, or different
83  * request code integers supplied to {@link #getActivity}, {@link #getActivities},
84  * {@link #getBroadcast}, or {@link #getService}.
85  *
86  * <p>If you only need one PendingIntent active at a time for any of the
87  * Intents you will use, then you can alternatively use the flags
88  * {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
89  * cancel or modify whatever current PendingIntent is associated with the
90  * Intent you are supplying.
91  */
92 public final class PendingIntent implements Parcelable {
93     private final IIntentSender mTarget;
94 
95     /** @hide */
96     @IntDef(flag = true,
97             value = {
98                     FLAG_ONE_SHOT,
99                     FLAG_NO_CREATE,
100                     FLAG_CANCEL_CURRENT,
101                     FLAG_UPDATE_CURRENT,
102 
103                     Intent.FILL_IN_ACTION,
104                     Intent.FILL_IN_DATA,
105                     Intent.FILL_IN_CATEGORIES,
106                     Intent.FILL_IN_COMPONENT,
107                     Intent.FILL_IN_PACKAGE,
108                     Intent.FILL_IN_SOURCE_BOUNDS,
109                     Intent.FILL_IN_SELECTOR,
110                     Intent.FILL_IN_CLIP_DATA
111             })
112     @Retention(RetentionPolicy.SOURCE)
113     public @interface Flags {}
114 
115     /**
116      * Flag indicating that this PendingIntent can be used only once.
117      * For use with {@link #getActivity}, {@link #getBroadcast}, and
118      * {@link #getService}. <p>If set, after
119      * {@link #send()} is called on it, it will be automatically
120      * canceled for you and any future attempt to send through it will fail.
121      */
122     public static final int FLAG_ONE_SHOT = 1<<30;
123     /**
124      * Flag indicating that if the described PendingIntent does not
125      * already exist, then simply return null instead of creating it.
126      * For use with {@link #getActivity}, {@link #getBroadcast}, and
127      * {@link #getService}.
128      */
129     public static final int FLAG_NO_CREATE = 1<<29;
130     /**
131      * Flag indicating that if the described PendingIntent already exists,
132      * the current one should be canceled before generating a new one.
133      * For use with {@link #getActivity}, {@link #getBroadcast}, and
134      * {@link #getService}. <p>You can use
135      * this to retrieve a new PendingIntent when you are only changing the
136      * extra data in the Intent; by canceling the previous pending intent,
137      * this ensures that only entities given the new data will be able to
138      * launch it.  If this assurance is not an issue, consider
139      * {@link #FLAG_UPDATE_CURRENT}.
140      */
141     public static final int FLAG_CANCEL_CURRENT = 1<<28;
142     /**
143      * Flag indicating that if the described PendingIntent already exists,
144      * then keep it but replace its extra data with what is in this new
145      * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
146      * {@link #getService}. <p>This can be used if you are creating intents where only the
147      * extras change, and don't care that any entities that received your
148      * previous PendingIntent will be able to launch it with your new
149      * extras even if they are not explicitly given to it.
150      */
151     public static final int FLAG_UPDATE_CURRENT = 1<<27;
152 
153     /**
154      * Exception thrown when trying to send through a PendingIntent that
155      * has been canceled or is otherwise no longer able to execute the request.
156      */
157     public static class CanceledException extends AndroidException {
CanceledException()158         public CanceledException() {
159         }
160 
CanceledException(String name)161         public CanceledException(String name) {
162             super(name);
163         }
164 
CanceledException(Exception cause)165         public CanceledException(Exception cause) {
166             super(cause);
167         }
168     }
169 
170     /**
171      * Callback interface for discovering when a send operation has
172      * completed.  Primarily for use with a PendingIntent that is
173      * performing a broadcast, this provides the same information as
174      * calling {@link Context#sendOrderedBroadcast(Intent, String,
175      * android.content.BroadcastReceiver, Handler, int, String, Bundle)
176      * Context.sendBroadcast()} with a final BroadcastReceiver.
177      */
178     public interface OnFinished {
179         /**
180          * Called when a send operation as completed.
181          *
182          * @param pendingIntent The PendingIntent this operation was sent through.
183          * @param intent The original Intent that was sent.
184          * @param resultCode The final result code determined by the send.
185          * @param resultData The final data collected by a broadcast.
186          * @param resultExtras The final extras collected by a broadcast.
187          */
onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)188         void onSendFinished(PendingIntent pendingIntent, Intent intent,
189                 int resultCode, String resultData, Bundle resultExtras);
190     }
191 
192     private static class FinishedDispatcher extends IIntentReceiver.Stub
193             implements Runnable {
194         private final PendingIntent mPendingIntent;
195         private final OnFinished mWho;
196         private final Handler mHandler;
197         private Intent mIntent;
198         private int mResultCode;
199         private String mResultData;
200         private Bundle mResultExtras;
FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler)201         FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
202             mPendingIntent = pi;
203             mWho = who;
204             mHandler = handler;
205         }
performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean serialized, boolean sticky, int sendingUser)206         public void performReceive(Intent intent, int resultCode, String data,
207                 Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
208             mIntent = intent;
209             mResultCode = resultCode;
210             mResultData = data;
211             mResultExtras = extras;
212             if (mHandler == null) {
213                 run();
214             } else {
215                 mHandler.post(this);
216             }
217         }
run()218         public void run() {
219             mWho.onSendFinished(mPendingIntent, mIntent, mResultCode,
220                     mResultData, mResultExtras);
221         }
222     }
223 
224     /**
225      * Retrieve a PendingIntent that will start a new activity, like calling
226      * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
227      * Note that the activity will be started outside of the context of an
228      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
229      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
230      *
231      * <p class="note">For security reasons, the {@link android.content.Intent}
232      * you supply here should almost always be an <em>explicit intent</em>,
233      * that is specify an explicit component to be delivered to through
234      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
235      *
236      * @param context The Context in which this PendingIntent should start
237      * the activity.
238      * @param requestCode Private request code for the sender
239      * @param intent Intent of the activity to be launched.
240      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
241      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
242      * or any of the flags as supported by
243      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
244      * of the intent that can be supplied when the actual send happens.
245      *
246      * @return Returns an existing or new PendingIntent matching the given
247      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
248      * supplied.
249      */
getActivity(Context context, int requestCode, Intent intent, @Flags int flags)250     public static PendingIntent getActivity(Context context, int requestCode,
251             Intent intent, @Flags int flags) {
252         return getActivity(context, requestCode, intent, flags, null);
253     }
254 
255     /**
256      * Retrieve a PendingIntent that will start a new activity, like calling
257      * {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
258      * Note that the activity will be started outside of the context of an
259      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
260      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.
261      *
262      * <p class="note">For security reasons, the {@link android.content.Intent}
263      * you supply here should almost always be an <em>explicit intent</em>,
264      * that is specify an explicit component to be delivered to through
265      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
266      *
267      * @param context The Context in which this PendingIntent should start
268      * the activity.
269      * @param requestCode Private request code for the sender
270      * @param intent Intent of the activity to be launched.
271      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
272      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
273      * or any of the flags as supported by
274      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
275      * of the intent that can be supplied when the actual send happens.
276      * @param options Additional options for how the Activity should be started.
277      * May be null if there are no options.
278      *
279      * @return Returns an existing or new PendingIntent matching the given
280      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
281      * supplied.
282      */
getActivity(Context context, int requestCode, @NonNull Intent intent, @Flags int flags, @Nullable Bundle options)283     public static PendingIntent getActivity(Context context, int requestCode,
284             @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
285         String packageName = context.getPackageName();
286         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
287                 context.getContentResolver()) : null;
288         try {
289             intent.migrateExtraStreamToClipData();
290             intent.prepareToLeaveProcess();
291             IIntentSender target =
292                 ActivityManagerNative.getDefault().getIntentSender(
293                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
294                     null, null, requestCode, new Intent[] { intent },
295                     resolvedType != null ? new String[] { resolvedType } : null,
296                     flags, options, UserHandle.myUserId());
297             return target != null ? new PendingIntent(target) : null;
298         } catch (RemoteException e) {
299         }
300         return null;
301     }
302 
303     /**
304      * @hide
305      * Note that UserHandle.CURRENT will be interpreted at the time the
306      * activity is started, not when the pending intent is created.
307      */
getActivityAsUser(Context context, int requestCode, @NonNull Intent intent, int flags, Bundle options, UserHandle user)308     public static PendingIntent getActivityAsUser(Context context, int requestCode,
309             @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
310         String packageName = context.getPackageName();
311         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
312                 context.getContentResolver()) : null;
313         try {
314             intent.migrateExtraStreamToClipData();
315             intent.prepareToLeaveProcess();
316             IIntentSender target =
317                 ActivityManagerNative.getDefault().getIntentSender(
318                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
319                     null, null, requestCode, new Intent[] { intent },
320                     resolvedType != null ? new String[] { resolvedType } : null,
321                     flags, options, user.getIdentifier());
322             return target != null ? new PendingIntent(target) : null;
323         } catch (RemoteException e) {
324         }
325         return null;
326     }
327 
328     /**
329      * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
330      * array of Intents to be supplied.  The last Intent in the array is
331      * taken as the primary key for the PendingIntent, like the single Intent
332      * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
333      * the resulting PendingIntent, all of the Intents are started in the same
334      * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
335      *
336      * <p class="note">
337      * The <em>first</em> intent in the array will be started outside of the context of an
338      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
339      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
340      * the first in the array are started in the context of the previous activity
341      * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
342      * </p>
343      *
344      * <p class="note">
345      * The <em>last</em> intent in the array represents the key for the
346      * PendingIntent.  In other words, it is the significant element for matching
347      * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
348      * its content will be the subject of replacement by
349      * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
350      * This is because it is the most specific of the supplied intents, and the
351      * UI the user actually sees when the intents are started.
352      * </p>
353      *
354      * <p class="note">For security reasons, the {@link android.content.Intent} objects
355      * you supply here should almost always be <em>explicit intents</em>,
356      * that is specify an explicit component to be delivered to through
357      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
358      *
359      * @param context The Context in which this PendingIntent should start
360      * the activity.
361      * @param requestCode Private request code for the sender
362      * @param intents Array of Intents of the activities to be launched.
363      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
364      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
365      * or any of the flags as supported by
366      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
367      * of the intent that can be supplied when the actual send happens.
368      *
369      * @return Returns an existing or new PendingIntent matching the given
370      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
371      * supplied.
372      */
getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags)373     public static PendingIntent getActivities(Context context, int requestCode,
374             @NonNull Intent[] intents, @Flags int flags) {
375         return getActivities(context, requestCode, intents, flags, null);
376     }
377 
378     /**
379      * Like {@link #getActivity(Context, int, Intent, int)}, but allows an
380      * array of Intents to be supplied.  The last Intent in the array is
381      * taken as the primary key for the PendingIntent, like the single Intent
382      * given to {@link #getActivity(Context, int, Intent, int)}.  Upon sending
383      * the resulting PendingIntent, all of the Intents are started in the same
384      * way as they would be by passing them to {@link Context#startActivities(Intent[])}.
385      *
386      * <p class="note">
387      * The <em>first</em> intent in the array will be started outside of the context of an
388      * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK
389      * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent.  (Activities after
390      * the first in the array are started in the context of the previous activity
391      * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.)
392      * </p>
393      *
394      * <p class="note">
395      * The <em>last</em> intent in the array represents the key for the
396      * PendingIntent.  In other words, it is the significant element for matching
397      * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)},
398      * its content will be the subject of replacement by
399      * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc.
400      * This is because it is the most specific of the supplied intents, and the
401      * UI the user actually sees when the intents are started.
402      * </p>
403      *
404      * <p class="note">For security reasons, the {@link android.content.Intent} objects
405      * you supply here should almost always be <em>explicit intents</em>,
406      * that is specify an explicit component to be delivered to through
407      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
408      *
409      * @param context The Context in which this PendingIntent should start
410      * the activity.
411      * @param requestCode Private request code for the sender
412      * @param intents Array of Intents of the activities to be launched.
413      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
414      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
415      * or any of the flags as supported by
416      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
417      * of the intent that can be supplied when the actual send happens.
418      *
419      * @return Returns an existing or new PendingIntent matching the given
420      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
421      * supplied.
422      */
getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options)423     public static PendingIntent getActivities(Context context, int requestCode,
424             @NonNull Intent[] intents, @Flags int flags, @Nullable Bundle options) {
425         String packageName = context.getPackageName();
426         String[] resolvedTypes = new String[intents.length];
427         for (int i=0; i<intents.length; i++) {
428             intents[i].migrateExtraStreamToClipData();
429             intents[i].prepareToLeaveProcess();
430             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
431         }
432         try {
433             IIntentSender target =
434                 ActivityManagerNative.getDefault().getIntentSender(
435                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
436                     null, null, requestCode, intents, resolvedTypes, flags, options,
437                     UserHandle.myUserId());
438             return target != null ? new PendingIntent(target) : null;
439         } catch (RemoteException e) {
440         }
441         return null;
442     }
443 
444     /**
445      * @hide
446      * Note that UserHandle.CURRENT will be interpreted at the time the
447      * activity is started, not when the pending intent is created.
448      */
getActivitiesAsUser(Context context, int requestCode, @NonNull Intent[] intents, int flags, Bundle options, UserHandle user)449     public static PendingIntent getActivitiesAsUser(Context context, int requestCode,
450             @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
451         String packageName = context.getPackageName();
452         String[] resolvedTypes = new String[intents.length];
453         for (int i=0; i<intents.length; i++) {
454             intents[i].migrateExtraStreamToClipData();
455             intents[i].prepareToLeaveProcess();
456             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
457         }
458         try {
459             IIntentSender target =
460                 ActivityManagerNative.getDefault().getIntentSender(
461                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
462                     null, null, requestCode, intents, resolvedTypes,
463                     flags, options, user.getIdentifier());
464             return target != null ? new PendingIntent(target) : null;
465         } catch (RemoteException e) {
466         }
467         return null;
468     }
469 
470     /**
471      * Retrieve a PendingIntent that will perform a broadcast, like calling
472      * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
473      *
474      * <p class="note">For security reasons, the {@link android.content.Intent}
475      * you supply here should almost always be an <em>explicit intent</em>,
476      * that is specify an explicit component to be delivered to through
477      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
478      *
479      * @param context The Context in which this PendingIntent should perform
480      * the broadcast.
481      * @param requestCode Private request code for the sender
482      * @param intent The Intent to be broadcast.
483      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
484      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
485      * or any of the flags as supported by
486      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
487      * of the intent that can be supplied when the actual send happens.
488      *
489      * @return Returns an existing or new PendingIntent matching the given
490      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
491      * supplied.
492      */
getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags)493     public static PendingIntent getBroadcast(Context context, int requestCode,
494             Intent intent, @Flags int flags) {
495         return getBroadcastAsUser(context, requestCode, intent, flags,
496                 new UserHandle(UserHandle.myUserId()));
497     }
498 
499     /**
500      * @hide
501      * Note that UserHandle.CURRENT will be interpreted at the time the
502      * broadcast is sent, not when the pending intent is created.
503      */
getBroadcastAsUser(Context context, int requestCode, Intent intent, int flags, UserHandle userHandle)504     public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
505             Intent intent, int flags, UserHandle userHandle) {
506         String packageName = context.getPackageName();
507         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
508                 context.getContentResolver()) : null;
509         try {
510             intent.prepareToLeaveProcess();
511             IIntentSender target =
512                 ActivityManagerNative.getDefault().getIntentSender(
513                     ActivityManager.INTENT_SENDER_BROADCAST, packageName,
514                     null, null, requestCode, new Intent[] { intent },
515                     resolvedType != null ? new String[] { resolvedType } : null,
516                     flags, null, userHandle.getIdentifier());
517             return target != null ? new PendingIntent(target) : null;
518         } catch (RemoteException e) {
519         }
520         return null;
521     }
522 
523     /**
524      * Retrieve a PendingIntent that will start a service, like calling
525      * {@link Context#startService Context.startService()}.  The start
526      * arguments given to the service will come from the extras of the Intent.
527      *
528      * <p class="note">For security reasons, the {@link android.content.Intent}
529      * you supply here should almost always be an <em>explicit intent</em>,
530      * that is specify an explicit component to be delivered to through
531      * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
532      *
533      * @param context The Context in which this PendingIntent should start
534      * the service.
535      * @param requestCode Private request code for the sender
536      * @param intent An Intent describing the service to be started.
537      * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
538      * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
539      * or any of the flags as supported by
540      * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
541      * of the intent that can be supplied when the actual send happens.
542      *
543      * @return Returns an existing or new PendingIntent matching the given
544      * parameters.  May return null only if {@link #FLAG_NO_CREATE} has been
545      * supplied.
546      */
getService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)547     public static PendingIntent getService(Context context, int requestCode,
548             @NonNull Intent intent, @Flags int flags) {
549         String packageName = context.getPackageName();
550         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
551                 context.getContentResolver()) : null;
552         try {
553             intent.prepareToLeaveProcess();
554             IIntentSender target =
555                 ActivityManagerNative.getDefault().getIntentSender(
556                     ActivityManager.INTENT_SENDER_SERVICE, packageName,
557                     null, null, requestCode, new Intent[] { intent },
558                     resolvedType != null ? new String[] { resolvedType } : null,
559                     flags, null, UserHandle.myUserId());
560             return target != null ? new PendingIntent(target) : null;
561         } catch (RemoteException e) {
562         }
563         return null;
564     }
565 
566     /**
567      * Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
568      *
569      * @return Returns a IntentSender object that wraps the sender of PendingIntent
570      *
571      */
getIntentSender()572     public IntentSender getIntentSender() {
573         return new IntentSender(mTarget);
574     }
575 
576     /**
577      * Cancel a currently active PendingIntent.  Only the original application
578      * owning a PendingIntent can cancel it.
579      */
cancel()580     public void cancel() {
581         try {
582             ActivityManagerNative.getDefault().cancelIntentSender(mTarget);
583         } catch (RemoteException e) {
584         }
585     }
586 
587     /**
588      * Perform the operation associated with this PendingIntent.
589      *
590      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
591      *
592      * @throws CanceledException Throws CanceledException if the PendingIntent
593      * is no longer allowing more intents to be sent through it.
594      */
send()595     public void send() throws CanceledException {
596         send(null, 0, null, null, null, null);
597     }
598 
599     /**
600      * Perform the operation associated with this PendingIntent.
601      *
602      * @param code Result code to supply back to the PendingIntent's target.
603      *
604      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
605      *
606      * @throws CanceledException Throws CanceledException if the PendingIntent
607      * is no longer allowing more intents to be sent through it.
608      */
send(int code)609     public void send(int code) throws CanceledException {
610         send(null, code, null, null, null, null);
611     }
612 
613     /**
614      * Perform the operation associated with this PendingIntent, allowing the
615      * caller to specify information about the Intent to use.
616      *
617      * @param context The Context of the caller.
618      * @param code Result code to supply back to the PendingIntent's target.
619      * @param intent Additional Intent data.  See {@link Intent#fillIn
620      * Intent.fillIn()} for information on how this is applied to the
621      * original Intent.
622      *
623      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
624      *
625      * @throws CanceledException Throws CanceledException if the PendingIntent
626      * is no longer allowing more intents to be sent through it.
627      */
send(Context context, int code, Intent intent)628     public void send(Context context, int code, Intent intent)
629             throws CanceledException {
630         send(context, code, intent, null, null, null);
631     }
632 
633     /**
634      * Perform the operation associated with this PendingIntent, allowing the
635      * caller to be notified when the send has completed.
636      *
637      * @param code Result code to supply back to the PendingIntent's target.
638      * @param onFinished The object to call back on when the send has
639      * completed, or null for no callback.
640      * @param handler Handler identifying the thread on which the callback
641      * should happen.  If null, the callback will happen from the thread
642      * pool of the process.
643      *
644      * @see #send(Context, int, Intent, android.app.PendingIntent.OnFinished, Handler)
645      *
646      * @throws CanceledException Throws CanceledException if the PendingIntent
647      * is no longer allowing more intents to be sent through it.
648      */
send(int code, OnFinished onFinished, Handler handler)649     public void send(int code, OnFinished onFinished, Handler handler)
650             throws CanceledException {
651         send(null, code, null, onFinished, handler, null);
652     }
653 
654     /**
655      * Perform the operation associated with this PendingIntent, allowing the
656      * caller to specify information about the Intent to use and be notified
657      * when the send has completed.
658      *
659      * <p>For the intent parameter, a PendingIntent
660      * often has restrictions on which fields can be supplied here, based on
661      * how the PendingIntent was retrieved in {@link #getActivity},
662      * {@link #getBroadcast}, or {@link #getService}.
663      *
664      * @param context The Context of the caller.  This may be null if
665      * <var>intent</var> is also null.
666      * @param code Result code to supply back to the PendingIntent's target.
667      * @param intent Additional Intent data.  See {@link Intent#fillIn
668      * Intent.fillIn()} for information on how this is applied to the
669      * original Intent.  Use null to not modify the original Intent.
670      * @param onFinished The object to call back on when the send has
671      * completed, or null for no callback.
672      * @param handler Handler identifying the thread on which the callback
673      * should happen.  If null, the callback will happen from the thread
674      * pool of the process.
675      *
676      * @see #send()
677      * @see #send(int)
678      * @see #send(Context, int, Intent)
679      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
680      * @see #send(Context, int, Intent, OnFinished, Handler, String)
681      *
682      * @throws CanceledException Throws CanceledException if the PendingIntent
683      * is no longer allowing more intents to be sent through it.
684      */
send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler)685     public void send(Context context, int code, Intent intent,
686             OnFinished onFinished, Handler handler) throws CanceledException {
687         send(context, code, intent, onFinished, handler, null);
688     }
689 
690     /**
691      * Perform the operation associated with this PendingIntent, allowing the
692      * caller to specify information about the Intent to use and be notified
693      * when the send has completed.
694      *
695      * <p>For the intent parameter, a PendingIntent
696      * often has restrictions on which fields can be supplied here, based on
697      * how the PendingIntent was retrieved in {@link #getActivity},
698      * {@link #getBroadcast}, or {@link #getService}.
699      *
700      * @param context The Context of the caller.  This may be null if
701      * <var>intent</var> is also null.
702      * @param code Result code to supply back to the PendingIntent's target.
703      * @param intent Additional Intent data.  See {@link Intent#fillIn
704      * Intent.fillIn()} for information on how this is applied to the
705      * original Intent.  Use null to not modify the original Intent.
706      * @param onFinished The object to call back on when the send has
707      * completed, or null for no callback.
708      * @param handler Handler identifying the thread on which the callback
709      * should happen.  If null, the callback will happen from the thread
710      * pool of the process.
711      * @param requiredPermission Name of permission that a recipient of the PendingIntent
712      * is required to hold.  This is only valid for broadcast intents, and
713      * corresponds to the permission argument in
714      * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
715      * If null, no permission is required.
716      *
717      * @see #send()
718      * @see #send(int)
719      * @see #send(Context, int, Intent)
720      * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
721      * @see #send(Context, int, Intent, OnFinished, Handler)
722      *
723      * @throws CanceledException Throws CanceledException if the PendingIntent
724      * is no longer allowing more intents to be sent through it.
725      */
send(Context context, int code, Intent intent, OnFinished onFinished, Handler handler, String requiredPermission)726     public void send(Context context, int code, Intent intent,
727             OnFinished onFinished, Handler handler, String requiredPermission)
728             throws CanceledException {
729         try {
730             String resolvedType = intent != null ?
731                     intent.resolveTypeIfNeeded(context.getContentResolver())
732                     : null;
733             int res = mTarget.send(code, intent, resolvedType,
734                     onFinished != null
735                             ? new FinishedDispatcher(this, onFinished, handler)
736                             : null,
737                     requiredPermission);
738             if (res < 0) {
739                 throw new CanceledException();
740             }
741         } catch (RemoteException e) {
742             throw new CanceledException(e);
743         }
744     }
745 
746     /**
747      * @deprecated Renamed to {@link #getCreatorPackage()}.
748      */
749     @Deprecated
getTargetPackage()750     public String getTargetPackage() {
751         try {
752             return ActivityManagerNative.getDefault()
753                 .getPackageForIntentSender(mTarget);
754         } catch (RemoteException e) {
755             // Should never happen.
756             return null;
757         }
758     }
759 
760     /**
761      * Return the package name of the application that created this
762      * PendingIntent, that is the identity under which you will actually be
763      * sending the Intent.  The returned string is supplied by the system, so
764      * that an application can not spoof its package.
765      *
766      * <p class="note">Be careful about how you use this.  All this tells you is
767      * who created the PendingIntent.  It does <strong>not</strong> tell you who
768      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
769      * passed between applications, so the PendingIntent you receive from an application
770      * could actually be one it received from another application, meaning the result
771      * you get here will identify the original application.  Because of this, you should
772      * only use this information to identify who you expect to be interacting with
773      * through a {@link #send} call, not who gave you the PendingIntent.</p>
774      *
775      * @return The package name of the PendingIntent, or null if there is
776      * none associated with it.
777      */
778     @Nullable
getCreatorPackage()779     public String getCreatorPackage() {
780         try {
781             return ActivityManagerNative.getDefault()
782                 .getPackageForIntentSender(mTarget);
783         } catch (RemoteException e) {
784             // Should never happen.
785             return null;
786         }
787     }
788 
789     /**
790      * Return the uid of the application that created this
791      * PendingIntent, that is the identity under which you will actually be
792      * sending the Intent.  The returned integer is supplied by the system, so
793      * that an application can not spoof its uid.
794      *
795      * <p class="note">Be careful about how you use this.  All this tells you is
796      * who created the PendingIntent.  It does <strong>not</strong> tell you who
797      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
798      * passed between applications, so the PendingIntent you receive from an application
799      * could actually be one it received from another application, meaning the result
800      * you get here will identify the original application.  Because of this, you should
801      * only use this information to identify who you expect to be interacting with
802      * through a {@link #send} call, not who gave you the PendingIntent.</p>
803      *
804      * @return The uid of the PendingIntent, or -1 if there is
805      * none associated with it.
806      */
getCreatorUid()807     public int getCreatorUid() {
808         try {
809             return ActivityManagerNative.getDefault()
810                 .getUidForIntentSender(mTarget);
811         } catch (RemoteException e) {
812             // Should never happen.
813             return -1;
814         }
815     }
816 
817     /**
818      * Return the user handle of the application that created this
819      * PendingIntent, that is the user under which you will actually be
820      * sending the Intent.  The returned UserHandle is supplied by the system, so
821      * that an application can not spoof its user.  See
822      * {@link android.os.Process#myUserHandle() Process.myUserHandle()} for
823      * more explanation of user handles.
824      *
825      * <p class="note">Be careful about how you use this.  All this tells you is
826      * who created the PendingIntent.  It does <strong>not</strong> tell you who
827      * handed the PendingIntent to you: that is, PendingIntent objects are intended to be
828      * passed between applications, so the PendingIntent you receive from an application
829      * could actually be one it received from another application, meaning the result
830      * you get here will identify the original application.  Because of this, you should
831      * only use this information to identify who you expect to be interacting with
832      * through a {@link #send} call, not who gave you the PendingIntent.</p>
833      *
834      * @return The user handle of the PendingIntent, or null if there is
835      * none associated with it.
836      */
837     @Nullable
getCreatorUserHandle()838     public UserHandle getCreatorUserHandle() {
839         try {
840             int uid = ActivityManagerNative.getDefault()
841                 .getUidForIntentSender(mTarget);
842             return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
843         } catch (RemoteException e) {
844             // Should never happen.
845             return null;
846         }
847     }
848 
849     /**
850      * @hide
851      * Check to verify that this PendingIntent targets a specific package.
852      */
isTargetedToPackage()853     public boolean isTargetedToPackage() {
854         try {
855             return ActivityManagerNative.getDefault()
856                 .isIntentSenderTargetedToPackage(mTarget);
857         } catch (RemoteException e) {
858             // Should never happen.
859             return false;
860         }
861     }
862 
863     /**
864      * @hide
865      * Check whether this PendingIntent will launch an Activity.
866      */
isActivity()867     public boolean isActivity() {
868         try {
869             return ActivityManagerNative.getDefault()
870                 .isIntentSenderAnActivity(mTarget);
871         } catch (RemoteException e) {
872             // Should never happen.
873             return false;
874         }
875     }
876 
877     /**
878      * @hide
879      * Return the Intent of this PendingIntent.
880      */
getIntent()881     public Intent getIntent() {
882         try {
883             return ActivityManagerNative.getDefault()
884                 .getIntentForIntentSender(mTarget);
885         } catch (RemoteException e) {
886             // Should never happen.
887             return null;
888         }
889     }
890 
891     /**
892      * @hide
893      * Return descriptive tag for this PendingIntent.
894      */
getTag(String prefix)895     public String getTag(String prefix) {
896         try {
897             return ActivityManagerNative.getDefault()
898                 .getTagForIntentSender(mTarget, prefix);
899         } catch (RemoteException e) {
900             // Should never happen.
901             return null;
902         }
903     }
904 
905     /**
906      * Comparison operator on two PendingIntent objects, such that true
907      * is returned then they both represent the same operation from the
908      * same package.  This allows you to use {@link #getActivity},
909      * {@link #getBroadcast}, or {@link #getService} multiple times (even
910      * across a process being killed), resulting in different PendingIntent
911      * objects but whose equals() method identifies them as being the same
912      * operation.
913      */
914     @Override
equals(Object otherObj)915     public boolean equals(Object otherObj) {
916         if (otherObj instanceof PendingIntent) {
917             return mTarget.asBinder().equals(((PendingIntent)otherObj)
918                     .mTarget.asBinder());
919         }
920         return false;
921     }
922 
923     @Override
hashCode()924     public int hashCode() {
925         return mTarget.asBinder().hashCode();
926     }
927 
928     @Override
toString()929     public String toString() {
930         StringBuilder sb = new StringBuilder(128);
931         sb.append("PendingIntent{");
932         sb.append(Integer.toHexString(System.identityHashCode(this)));
933         sb.append(": ");
934         sb.append(mTarget != null ? mTarget.asBinder() : null);
935         sb.append('}');
936         return sb.toString();
937     }
938 
describeContents()939     public int describeContents() {
940         return 0;
941     }
942 
writeToParcel(Parcel out, int flags)943     public void writeToParcel(Parcel out, int flags) {
944         out.writeStrongBinder(mTarget.asBinder());
945     }
946 
947     public static final Parcelable.Creator<PendingIntent> CREATOR
948             = new Parcelable.Creator<PendingIntent>() {
949         public PendingIntent createFromParcel(Parcel in) {
950             IBinder target = in.readStrongBinder();
951             return target != null ? new PendingIntent(target) : null;
952         }
953 
954         public PendingIntent[] newArray(int size) {
955             return new PendingIntent[size];
956         }
957     };
958 
959     /**
960      * Convenience function for writing either a PendingIntent or null pointer to
961      * a Parcel.  You must use this with {@link #readPendingIntentOrNullFromParcel}
962      * for later reading it.
963      *
964      * @param sender The PendingIntent to write, or null.
965      * @param out Where to write the PendingIntent.
966      */
writePendingIntentOrNullToParcel(@ullable PendingIntent sender, @NonNull Parcel out)967     public static void writePendingIntentOrNullToParcel(@Nullable PendingIntent sender,
968             @NonNull Parcel out) {
969         out.writeStrongBinder(sender != null ? sender.mTarget.asBinder()
970                 : null);
971     }
972 
973     /**
974      * Convenience function for reading either a Messenger or null pointer from
975      * a Parcel.  You must have previously written the Messenger with
976      * {@link #writePendingIntentOrNullToParcel}.
977      *
978      * @param in The Parcel containing the written Messenger.
979      *
980      * @return Returns the Messenger read from the Parcel, or null if null had
981      * been written.
982      */
983     @Nullable
readPendingIntentOrNullFromParcel(@onNull Parcel in)984     public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) {
985         IBinder b = in.readStrongBinder();
986         return b != null ? new PendingIntent(b) : null;
987     }
988 
PendingIntent(IIntentSender target)989     /*package*/ PendingIntent(IIntentSender target) {
990         mTarget = target;
991     }
992 
PendingIntent(IBinder target)993     /*package*/ PendingIntent(IBinder target) {
994         mTarget = IIntentSender.Stub.asInterface(target);
995     }
996 
997     /** @hide */
getTarget()998     public IIntentSender getTarget() {
999         return mTarget;
1000     }
1001 }
1002