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